DigiPress

Highly Flexible WordPress Theme

ReactのJSXで条件によって要素を任意のHTMLタグで括る方法

Webデザイン・アプリ開発

ReactJSX を利用すると、ビューの構築を HTML ライクな構文で組めます。

その中で、よくあるケースとして URL の有無によってアンカー(a)タグで要素全体をラップするか否かを判定して出力したい場合があります。

このように React の JSX で条件分岐して要素をラップする場合は、以下の方法で対応できます。

方法1 : 先にコンテンツをまとめておく(変数化)

例えば、リンク(URL)の指定があればアンカータグでラップしたい要素を予め変数に代入しておき、最後にリンクの有無をチェックして指定があれば、アンカー(JSX)で変数をラップします。

サンプルコード
// ラップする要素(アンカーで括る前のコンテンツ)を変数に代入
const component = (
  <figure className={ this.props.className }>
    <img src={ this.props.imageUrl }>
    <figcaption>
      { this.props.caption }
    </figcaption>
  </figure>
)


// URL があればアンカータグで括る
if ( this.props.url ) {
  return (
    <a
      href={ this.props.url }
      className='image-anchor'
      rel={ this.props.newTab ? 'noopener noreferrer' : undefined }
    >
      { component }
    </a>
  )
}

return component

方法2 : コンポーネント化して利用する(汎用的)

より汎用的に、かつ JSX として視覚的に可読性が高い方法としては、条件分岐をコンポーネント化してしまうことです。

conditional-wrapper.jsラップ判定用の js
const ConditionalWrapper = ( { condition, wrapper, children } ) => condition ? wrapper(children) : children

export default ConditionalWrapper

このコンポーネント化した ConditionalWrapper は、以下のように利用します。

ビュー用の js
// conditional-wrapper.js をロード
import ConditionalWrapper from '/components/conditional-wrapper';

// ... なんやかんや色んな処理 ...


// ConditionalWrapper で括る
<ConditionalWrapper
  condition={ this.props.url }  // 条件(URLの有無)
  wrapper={ children => (  // URLがあればアンカータグで括る
    <a
      href={ this.props.url }
      className='image-anchor'
      rel={ this.props.newTab ? 'noopener noreferrer' : undefined }
    >
      { children }
    </a>
  ) }
>

  // ラップする要素
  <figure className={ this.props.className }>
    <img src={ this.props.imageUrl }>
    <figcaption>
      { this.props.caption }
    </figcaption>
  </figure>

</ConditionalWrapper>

この方法であれば、条件分岐のチェックを conditional-wrapper.js にまとめておき、必要な箇所で import してコンポーネント化した ConditionalWrapper を用いて、ラップする条件(condition)とラッパー要素(wrapper)を指定するだけで要件を満たせます。

Share / Subscribe
Facebook Likes
Tweets
Hatena Bookmarks
Pinterest
Pocket
Feedly
Send to LINE