保存されたtextareaからのReactの表示改行


86

Facebookを使用しReactます。設定ページに、textareaユーザーが複数行のテキスト(私の場合は住所)を入力できる複数行があります。

<textarea value={address} />

アドレスを表示しようとすると、のように{address}、改行が表示されず、すべて1行になります。

<p>{address}</p>

これを解決する方法はありますか?

回答:


248

JSを使用する理由はありません。white-spaceCSSプロパティを使用して、ブラウザに改行の処理方法を簡単に伝えることができます。

white-space: pre-line;

プレライン

空白のシーケンスは折りたたまれています。改行文字、、、<br>および必要に応じて行ボックスを埋めるために行が分割されます。

このデモをチェックしてください:

<style>
  #p_wrap {
    white-space: pre-line;
  }
</style>

<textarea id="textarea"></textarea>
<p id="p_standard"></p>
<hr>
<p id="p_wrap"></p>
<script>
  textarea.addEventListener('keypress', function(e) {
    p_standard.textContent = e.target.value
    p_wrap.textContent = e.target.value
  })
</script>

プレラインのブラウザサポート


これは複数の方法で機能します。変数を介してJSXで改行(<br />)をレンダリングしようとすると、改行を追加する代わりにマークアップを「安全に」レンダリングします。このCSSでエスケープ文字を使用すると、その安全メカニズムを回避し、前述の問題を修正できます。
bvoyelr 2017

とても素敵でシンプルなソリューション。これで、すべての改行文字がtexareaで期待どおりに機能します。
ナミッシュ​​2018年

31

これは予想されることです。改行(\ n)文字をHTML改行に変換する必要があります

reactでの使用に関する記事:React Newline to break(nl2br)

記事を引用するには:

Reactのすべてが関数であることを知っているので、実際にこれを行うことはできません

this.state.text.replace(/(?:\r\n|\r|\n)/g, '<br />')

DOMノードが内部にある文字列が返されるため、文字列のみである必要があるため、これも許可されません。

次に、次のようなことを試すことができます。

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    {item}
    <br/>
  )
})}    

Reactは純粋関数であり、2つの関数を並べることができるため、これも許可されません。

tldr。解決

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    <span>
      {item}
      <br/>
    </span>
  )
})}

これで、各改行をスパンでラップしています。スパンにはインライン表示があるため、これは正常に機能します。これで、実用的なnl2br改行ソリューションが得られました


ありがとうマーク、魅力のように機能します。ここに答えを出すチャンスはありますか?Stackoverflowは外部リンクを好みません(消える可能性があり、回答のリストを表示するのが難しくなります...)、私はあなたの回答を正しいものとしてマークします。
denislexic 2016年

4
他の人への注意:スパンはループ内にあるため、スパンにキー属性を追加する必要もあります。....map(function (item, i) { return <span key={i}>{item}<br/></span> })
つまり

1
素晴らしい答えです!これは私にとって役に立ちました。また、複数の改行がある場合は<br />、最後のアイテムの超過がレンダリングされ ないようにすることができます....map(function (item, i, arr) { return <span key={i}>{item}{ arr.length-1 === i ? null : <br/>}</span> }).map()
Lasha 2016年

1
どうやってこれを機能させたのかわかりません。私は、<TEXTAREA>に表示されますすることである[object Object]
エド。

@エド。textareaではなくHTMLテキストを表示することです。それは役に立ちますか?
denislexic 2017年

11

解決策はwhite-spacetextarea:のコンテンツを表示する要素にプロパティを設定することです。

white-space: pre-line;

4

スタンドアロンコンポーネントを使用したPeteの以前の提案は、1つの重要な点を見逃していますが、優れたソリューションです。リストにはキーが必要です。私はそれを少し調整しました、そして私のバージョン(コンソール警告なし)は次のようになります:

const NewLineToBr = ({ children = '' }) => children.split('\n')
  .reduce((arr, line, index) => arr.concat(
    <Fragment key={index}>
      {line}
      <br />
    </Fragment>,
  ), [])

React16のフラグメントを使用します


キーとしてのインデックスは、マップされたデータが「静的」であり、そのライフサイクルで変更されないことが確実な場合にのみ安全です。そうでない場合、問題が発生する可能性があります。
enapupe

1

React 16以降、コンポーネントは要素の配列を返すことができます。つまり、次のようなコンポーネントを作成できます。

export default function NewLineToBr({children = ""}){
  return children.split('\n').reduce(function (arr,line) {
    return arr.concat(
      line,
      <br />
    );
  },[]);
}

あなたはこのように使うでしょう:

<p>
  <NewLineToBr>{address}</NewLineToBr>
</p>

'\ n'を '\\ n'に変更する必要がありました。
dustydojo

1

webitバージョンが大好きです。フラグメントコンポーネントについては知りませんでした。とても便利です。ただし、reduceメソッドを使用する必要はありません。地図で十分です。また、リストにはreactでキーが必要ですが、反復メソッドのインデックスを使用するのは悪い習慣です。eslintは、混乱のバグが発生するまで、警告の中でこれを壊し続けました。したがって、次のようになります。

const NewLine = ({ children }) =>
   children.split("\n").map(line => (
    <Fragment key={uuidv4()}>
      {line}
      <br />
    </Fragment>
  ));

1
Reactでuuidをキーとして使用することはお勧めできません。これは、新しいレンダリングが行われるたびに、この要素が新しいものと見なされ、DOMが適応されるためです。
enapupe
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.