📘

ReactのState配列操作

に公開

State配列

ReactでState配列を表示したり操作するUIはよくあると思います。しかし、ReactのState配列ならではの注意点があり、使うメソッドを気をつける必用があります。
例えば、State配列末尾に追加する場合はpushでは無くconcatを使う必要があります。
理由は、配列を書き換えずに更新する必用がある為です。

それでは、よく使う操作を説明いたします。

追加

useArrayaddItemを実装しました。
concatを使用して追加するコードです。重要な部分は以下の通りです。

  • ベースの配列.concat(追加したい値)です
  • concatで新しい値を追加します
import { useState } from 'react';

type Item = {
  id: number;
  name: string;
};

export const useArray = () => {
  const [state, setState] = useState<Item[]>([]);

  return {
    items: state,
    /**
     * 末尾に追加
     * concatを使用
     */
    addItem: () =>
      setState((_state) =>
        _state.concat({
          id: _state.length + 1,
          name: '追加された値',
        }),
      ),
  };
};

const Component: React.FC = () => {
  const { items, addItem } = useArray();

  return (
    <>
      <button onClick={addItem}>追加</button>

      <ul>
        {items.map((item) => (
          <li key={item.id}>{JSON.stringify(item)}</li>
        ))}
      </ul>
    </>
  );
};
操作シーン

削除

useArrayremoveItemを実装しました。
filterを使用して配列の要素除外するコードです。重要な部分は以下の通りです。

  • ベースの配列.filter(条件)です
  • 条件に一致した要素を配列から除外します
  • 高階関数を使いidを束縛するとシンプルに実装できます
import { useState } from 'react';

type Item = {
  id: number;
  name: string;
};

export const useArray = () => {
  const [state, setState] = useState<Item[]>([]);

  return {
    items: state,
    /**
     * 末尾に追加
     * concatを使用
     */
    addItem: () =>
      setState((_state) =>
        _state.concat({
          id: _state.length + 1,
          name: '追加された値',
        }),
      ),
    /**
     * 要素を削除
     * filterを使用
     */
    removeItem: (selectedId: Item['id']) => () =>
      setState((_state) => _state.filter((o) => o.id !== selectedId)),
  };
};

const Component: React.FC = () => {
  const { items, addItem, removeItem } = useArray();

  return (
    <>
      <button onClick={addItem}>追加</button>

      <ul>
        {items.map((item) => (
          <li key={item.id}>
            {JSON.stringify(item)}
            <button onClick={removeItem(item.id)}>削除</button>
          </li>
        ))}
      </ul>
    </>
  );
};
操作シーン

置換

useArrayreplaceItemを実装しました。
mapを使用して配列の要素置換するコードです。重要な部分は以下の通りです。

  • ベースの配列.map(条件と値)です
    • 条件に一致する場合は、新しい値を返却する
    • 条件に一致しない場合は、そのまま値を返却する
  • 高階関数を使いidを束縛するとシンプルに実装できます
import { useState } from 'react';

type Item = {
  id: number;
  name: string;
};

export const useArray = () => {
  const [state, setState] = useState<Item[]>([]);

  return {
    items: state,
    /**
     * 末尾に追加
     * concatを使用
     */
    addItem: () =>
      setState((_state) =>
        _state.concat({
          id: _state.length + 1,
          name: '追加された値',
        }),
      ),
    /**
     * 要素を削除
     * filterを使用
     */
    removeItem: (selectedId: Item['id']) => () =>
      setState((_state) => _state.filter((o) => o.id !== selectedId)),
    /**
     * 要素を置換
     * mapを使用
     */
    replaceItem: (selectedId: Item['id']) => () =>
      setState((_state) =>
        _state.map((o) =>
          o.id === selectedId ? { ...o, name: '置換された値' } : o,
        ),
      ),
  };
};

const Component: React.FC = () => {
  const { items, addItem, removeItem, replaceItem } = useArray();

  return (
    <>
      <button onClick={addItem}>追加</button>

      <ul>
        {items.map((item) => (
          <li key={item.id}>
            {JSON.stringify(item)}
            <button onClick={removeItem(item.id)}>削除</button>
            <button onClick={replaceItem(item.id)}>置換</button>
          </li>
        ))}
      </ul>
    </>
  );
};
操作シーン

降順にソート

useArrayorderByDescを実装しました。
toReversedを使用して配列を降順にするコードです。重要な部分は以下の通りです。

  • reverseではなく、toReversedを使用する
import { useState } from 'react';

type Item = {
  id: number;
  name: string;
};

export const useArray = () => {
  const [state, setState] = useState<Item[]>([]);

  return {
    items: state,
    /**
     * 末尾に追加
     * concatを使用
     */
    addItem: () =>
      setState((_state) =>
        _state.concat({
          id: _state.length + 1,
          name: '追加された値',
        }),
      ),
    /**
     * 要素を削除
     * filterを使用
     */
    removeItem: (selectedId: Item['id']) => () =>
      setState((_state) => _state.filter((o) => o.id !== selectedId)),
    /**
     * 要素を置換
     * mapを使用
     */
    replaceItem: (selectedId: Item['id']) => () =>
      setState((_state) =>
        _state.map((o) =>
          o.id === selectedId ? { ...o, name: '置換された値' } : o,
        ),
      ),
    /**
     * 降順にソート
     * toReversedを使用
     */
    orderByDesc: () => setState((_state) => _state.toReversed()),
  };
};

const Component: React.FC = () => {
  const { items, addItem, removeItem, replaceItem, orderByDesc } = useArray();

  return (
    <>
      <div>
        <button onClick={addItem}>追加</button>
        <button onClick={orderByDesc}>降順</button>
      </div>

      <ul>
        {items.map((item) => (
          <li key={item.id}>
            {JSON.stringify(item)}
            <button onClick={removeItem(item.id)}>削除</button>
            <button onClick={replaceItem(item.id)}>置換</button>
          </li>
        ))}
      </ul>
    </>
  );
};
操作シーン

chot Inc. tech blog

Discussion