【React】Stateに配列を持つ場合の注意点

Reactを初学者に教える機会があり、その時によくハマりがちなのが「stateに配列でデータを持たせた時に、正しく更新できていない」ケースです。 エラーで落ちるわけでなく、renderがかからない等の気づきにくい不具合なので、原因特定がしにくいですが大体はこの記事の例に収まると思います。

前提条件

  • reactの初級者向け
  • コンポーネントのstateに配列でデータを保持している

概要

stateに配列としてデータを持っていて更新する場合、取得した配列を破壊的に変更してはいけません。 具体的には要素追加のpushや要素削除のspliceなどがあたります。

// state定義
this.state = {
  list : []
}

// ...略

let { list } = this.state;
// 要素の追加
list.push("Test"); // -> NG
// 要素の削除
list.splice(0,1); // -> NG

詳しく解説すると、let { list } = this.stateで取得したlistが参照渡しであるため、 内容を破壊的に変更するとsetState()を待たずして値を書き換えてしまうためです。

// 実質下記の記法と同じ
// setState以外の方法でstateを書き換えてもrenderが走りません
// 要素の追加
this.state.list.push("Test"); // -> NG
// 要素の削除
this.state.list.splice(0,1); // -> NG

解決策

スプレッド演算子...Array.from()を使って、別インスタンスとして配列を持たせてから変更しましょう。

// スプレッド演算子で配列を展開し、同じ値を持った別配列として再定義
let copyList = [...this.state.list];
// Array.from()でもOKです
// copyList = Array.from(this.state.list);

copyList.push("Test"); // -> OK
copyList.splice(0,1); // -> OK

this.setState({
  list : copyList,
})

まとめ

今回はreact初学者が陥りがちなstate内の配列の扱い方についてご紹介しました。 ぱっと見は動作しますが、renderが正しいタイミングでかからない等の不具合の原因となるので、しっかりと頭に入れておきましょう。

SNSでシェアする