JavaScriptに関するお知らせ

SINCE2019
>
【JS】Reactのループを逆順にする方法いろいろ
ReactJavaScript

【JS】Reactのループを逆順にする方法いろいろ


こんにちは!深夜にReact書くと型が適当になりがち。 Mizutani(@sirycity) です。anyany~

今日はReactでめっちゃ使う(というかDOMの描画で使う)ループを反対にする方法について色々書きます。

はじめに

Reactのループ、基本的にはこんな感じです。これが基本系。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']

  <ul>
    {
      arr.map((e, i) => 
        <li key={i}>{e}</li>
      )
    }
  </ul>
}

これは実際にはこんな感じになる↓

<ul>
  <li>さいしょ</li>
  <li>つぎ</li>
  <li>さいご</li>
</ul>

すごいシンプルね。でも、逆順にしたい時もあるでしょ?こんな感じに↓

<ul>
  <li>さいご</li>
  <li>つぎ</li>
  <li>さいしょ</li>
</ul>

この方法について考えていきます。

逆順にする方法いろいろ

reverseを使う

一番簡単なのが.reverse()を使う方法...

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']
  // 逆にする
  const reversedArr = arr.reverse()

  <ul>
    {
      reversedArr.map((e, i) => 
        <li key={i}>{e}</li>
      )
    }
  </ul>
}

いやこれで良いと思うじゃん?ダメなんだよなこれが。これで良かったら記事にしてない

有名な話ですが、JSのreverseは破壊的変更のため、Reactとの相性が最悪です。というか現代のJSとの相性が最悪。具体的には順番がでたらめになる可能性があります。どういう時になるかはあんま詳しくないけど。非破壊的なreverseはJS界隈で待ち望まれている機能の一つですね。

reduceRightを使う

.reduceRight()を使って配列をひっくり返すのはわりとベターな方法です。こう。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']
  // 逆にする
  const reversedArr = arr.reduceRight((p, c) => [...p, c], [])

  <ul>
    {
      reversedArr.map((e, i) => 
        <li key={i}>
          { e }
        </li>
      )
    }
  </ul>
}

reduceRight、いつ使うんだ?って思っていたあなた。非破壊的に配列をひっくり返すこんな使い方があるんです!すごい!...ただ、reduce本来の使い方とは異なるので列が長くなってくると重い。ここは注意。

mapを2回使う

reduceRightじゃなくてmapで配列を反転。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']
  // 逆にする
  const reversedArr = arr.map((_, i, a) => a[a.length - 1 - i])

  <ul>
    {
      reversedArr.map((e, i) => 
        <li key={i}>{e}</li>
      )
    }
  </ul>
}

これもかなり良い。ちなみにmapを頑張って1回に縮めることもできる。こう。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']

  <ul>
    {
      arr.map((_, i, a) => (
        <li key={i}>
          {a[a.length - 1 - i]}
        </li>
      ))
    }
  </ul>
}

スプレッド構文を使う

スプレッドで配列をばらした後もう一度まとめるだけ。reverseはその後普通に使う。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']
  // 逆にする
  const reversedArr = [...arr].reverse()

  <ul>
    {
      reversedArr.map((e, i) => 
        <li key={i}>{e}</li>
      )
    }
  </ul>
}

最強。めっちゃ良い。一度描画したら順番が変わらない配列はこれで良いと思う。 速度?わからん

CSSのorderを使う

でも、配列が逆になったりまた戻ったりまた逆になったりする配列は↑のmapとかスプレッドとか使えない。↑の使うと逆になった後にまた戻すとかは面倒です。そういう時に使えるのがCSSのorder使う方法。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']

  <ul style={{ display: 'flex' }}>
    {
      arr.map((e, i) => 
        <li key={i} style={{order: -i}}>
          {e}
        </li>
      )
    }
  </ul>
}

配列自体はそのまま出力するけど、flex orderを負の値にすることで逆向きに描画していく方法です。mapのやつとどっちが早いかはわかんないけど、自由度はこっちが上。例えば状態によって逆にするかしないかとかもできます。こう。

const foo =  () =>  {
  const arr = ['さいしょ', 'つぎ', 'さいご']
  // 反転するかしないか
  const isReversed = true

  <ul style={{ display: 'flex' }}>
    {
      arr.map((e, i) => 
        <li key={i} style={{
          order:isReversed ? -i : i
        }}>
          {e}
        </li>
      )
    }
  </ul>
}

って考えるとこの方法が最強な気がする。

最後に

静的な配列はスプレッド、動的な配列はflexorderがいいかなというのが所感です。配列を逆にすることは結構あるので(たぶん)、ぜひとも参考にしてね!

(reverseが非破壊になればこんなことする必要もないんだけどね。非破壊にならないかなー)

PREV
2021-01-24
【JS】ブログをGatsby.jsからNext.jsに移行して良かった事と悪かった事

NEXT
2021-01-30
【JS】named exportとdefault exportの違いやReactでの使い分け