22
Help us understand the problem. What are the problem?

posted at

updated at

Reactで改行コード\nの入っているテキストを改行したまま表示する方法

テキストエリア等で改行されたテキストを改行したまま表示したいときの方法を共有します。

方法1 CSSを利用

コメントから教えていただきました。
改行したい部分に以下のCSSを適用します。

white-space: pre-wrap;

方法2 改行コードを置換する

よく見るのはテキスト中の改行コード\n<br />に置換する方法だと思う。

class Message extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      message: 'これは、\nテキスト\nです。',
    }
  }

  render() {
    return (
      <div
        dangerouslySetInnerHTML={{
          __html: this.state.message.replace(/\n/g, '<br />')
        }}
      />
    )
  }
}

しかし、この方法だとXSSの脆弱性を生み出す可能性があるためできるだけ避けたい。

よって、改行タグ<br />をHTMLとして置換するのではなく、JSXの要素として置換できないか考えた。

結果として、以下のような構成になった。

class Message extends React.Component {
  // ...

  render() {
    return (
      <div>{
        this.state.message.split('\n').map((str, index) => (
          <React.Fragment key={index}>{str}<br /></React.Fragment>
        ))
      }</div>
    )
  }
}

テキスト中の改行コードで分割して作られた配列でmap関数で繰り返し処理をして、JSX要素を戻り値とした。
この方法であれば、悪意のあるユーザーがテキストにhtml要素を入力した場合にも文字列として扱われるため、XSSの脆弱性は抑えられる。

なお、map関数内の<React.Fragment />とは、戻り値が1つの要素しか指定でいないReactの制約を外してくれる便利な構文である。

追記(2021/11/16):末尾に不要な改行が含まれてしまう

@little_wolf513さんからコメントにてご教授いただきました。ありがとうございます!

方法2でご紹介した内容だと、余計な改行が文字列の末尾に追加されてしまいます。多くの場合、末尾に改行コードが含まれることはないので修正するべき点だと思います。

以下が改善後のコードです。

export default function App() {
  const messege = "Hello\nReact\n!"

  // 文字列を改行コードで分割して改行タグに置換
  const lbToBr = (txt) => {
    return (
        txt.split(/(\n)/g).map(t => (t === '\n')?<br/>:t)
    )
  }

  // 画面に表示
  return (
    <div>
      {lbToBr(messege)}
    </div>
  );
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
22
Help us understand the problem. What are the problem?