// Nice cat :3

ゼロ歳児と戦うフロントエンドエンジニア

Reactで「閉じろ」と怒られる

たとえば、商品名の一覧を表示したいとき。

list(items){
  return (
    items.map( item => <li>{ item.name }</li> )
  )
} 
      
render() {
  const { items } = this.props;
  return(
    <ul>
      { this.list(items); }
    </ul>
  );
}

こんなの、よく書きますね。
これは怒られません。正しい。
上記に加えて、this.props.optionsに値があれば、オプションを表示したいとき。

options(opt){
  return (
    <dd>{ opt.option01 }</dd>
    <dd>{ opt.option02 }</dd>
    <dd>{ opt.option03 }</dd>
  )
}

list(items){
  return (
    items.map( item => <li>{ item.name }</li> )
  )
} 
      
render() {
  const { items, options } = this.props;
  return (
    <ul>
      { this.list(items) }
    </ul>
    <dl>
      { options && this.options(options) }
    </dl>
  );
}

なんて書くと、Adjacent JSX elements must be wrapped in an enclosing tagと怒られます。

Module build failed: SyntaxError: /PATH/TO/YOUR/SCRIPT/FILE.js: Adjacent JSX elements must be wrapped in an enclosing tag 
   |       return (
   |           <dd>{ opt.option01 }</dd>
 > |           <dd>{ opt.option02 }</dd>
   |           ^
   |           <dd>{ opt.option03 }</dd>

このエラーメッセージを単に「隣り合う要素は単一のタグでラップされなければならない」と解釈してしまい、(・3・)あるぇ〜?どれも<dd>で括ってあるのになぁ〜?などと考えてしまったのですが、そうではなく、「隣接要素たちは単一のタグでラップされていなければならない」ということでした。
隣接要素というのはみんな大好きCSSでも登場する、隣接要素です。
どっちかっていうと兄弟要素な気もしますが。
セレクタでいうとE + *とかE ~ *にあたります。わからん人はMDNでも見てください。

なので、上記エラーを解消するには、

options(opt){
  return (
    <dl>
      <dd>{ opt.option01 }</dd>
      <dd>{ opt.option02 }</dd>
      <dd>{ opt.option03 }</dd>
    </dl>
  )
}

と、<dd>たちを括ってあげれば良いのでした。

なお、さまざまな事情からどうしてもタグで括るという対応ができない場合は、配列にして返してあげると通ります。
listで返しているitems.map( item => <li>{ item.name }</li> )も、結局のところ個々の要素の配列なので、隣接要素という扱いではないのかなと思っています。たぶん。

よく調べてないけど。