かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

React 文字列を改行付きにして出力したい

APIからエラーの時、改行コード付きの文字列が返ってくるので、改行を <br> に変換して出力したかったのメモ

例えばこんな文字列を改行させて表示させたい

const msg = "星宮いちご\n霧矢あおい\n紫吹蘭";

タグが入っていても文字列は文字列として出力される

改行コードを <br> に変換するのは /\n/g/\r\n|\n/g とかで replace すれば OK APIから返ってくるようなデータなら /\n/g で良さそうな気がする

str.replace で変換したものを children として出力しようとしても文字列なので文字列として出力される

// const msg = "星宮いちご\n霧矢あおい\n紫吹蘭";
const component = ({ msg }) => {
  const text = msg.replace(/\n/g, '<br />');
  return <div>{text}</div>;
}

👉 星宮いちご<br />霧矢あおい<br />紫吹蘭 という文字列が出力される

<div dangerouslySetInnerHTML={{__html: text}} /> で HTML タグを出力できるけど、あまり使いたくない方法なので別の方法にしたい。

<br /> タグを JSX で認識できる形にしなければならない

JSX は配列が扱えるので、改行コードで分割して直接 JSX な要素を作ってしまえばOK

// const msg = "星宮いちご\n霧矢あおい\n紫吹蘭";
const component = ({ msg }) => {
  const texts = msg.split("\n").map((item, index) => {
    // <></> は key を設定できないので、<React.Fragment /> を使う
    return (
      <React.Fragment key={index}>{item}<br /></React.Fragment>
    );
  });
  return <div>{texts}</div>;
}

👇

<div>
  星宮いちご<br />
  霧矢あおい<br />
  紫吹蘭<br />
</div>

<br /> タグが入り改行はできているが、最後の要素に不要な改行タグが付いてしまう。

/n (改行コード) だけを <br /> に変換する

str.split はキャプチャが使えるようなのでこれを利用する

RegExp で分割して結果に区切り文字列の一部を含める
separator がキャプチャの括弧 () を含む正規表現である場合、一致した結果が配列に含まれます。
cf. String.prototype.split() - JavaScript | MDN

つまり

const msg = "星宮いちご\n霧矢あおい\n紫吹蘭";
msg.split(/(\n)/);
// => ["星宮いちご", "↵", "霧矢あおい", "↵", "紫吹蘭"]

改行コードも配列の1要素になるので、この配列をループで回して改行コードなら <br /> タグに変換すれば良い。

// const msg = "星宮いちご\n霧矢あおい\n紫吹蘭";
const component = ({ msg }) => {
  const texts = msg.split(/(\n)/).map((item, index) => {
    return (
      <React.Fragment key={index}>
        { item.match(/\n/) ? <br /> : item }
      </React.Fragment>
    );
  });
  return <div>{texts}</div>;
}

👇

<div>
  星宮いちご
  <br />
  霧矢あおい
  <br />
  紫吹蘭
</div>

改行タグは React.createElement('br') でも作れる。
 
全部に Fragment が入ってチョット壮大すぎる気もするけど
₍ ᐢ. ̫ .ᐢ ₎👌 ヨシ!!

SAMPLE

See the Pen JSX: display <br /> by strings by KIKIKI (@kikiki_kiki) on CodePen.