Upgrade to Pro — share decks privately, control downloads, hide ads and more …

更新系と状態

uhyo
April 23, 2025

 更新系と状態

2025-04-23 Exploring State - LayerX Web Frontend Night

uhyo

April 23, 2025
Tweet

More Decks by uhyo

Other Decks in Technology

Transcript

  1. データを編集したときどうする? export const useData = ( page: number, ): {

    items: Item[]; totalPages: number } => { return use(fetchWithCache(page)); }; useさん「ステートを更新したい? うちそれやってないんで」 13
  2. 実際の実装 const { items: fetchedItems, totalPages } = useData(currentPage); const

    [itemsLocalDiff, setItemsLocalDiff] = useState(new Map()); const items = useMemo(() => { return fetchedItems.map((item) => { const localDiff = itemsLocalDiff.get(item.id); if (localDiff) { return { ...item, description: localDiff.description }; } return item; }); }, [fetchedItems, itemsLocalDiff]); 17 2 つ の ス テ ー ト を useMemo 内 で 合 成 してitemsを得ている
  3. 比較してみよう 18 fetchedItems ネットワーク localDiffs items 更新 items ネットワーク 更新

    ステートが分かれており、 それぞれの更新理由が明確 1つのステートが複数の 理由で更新される
  4. 普通の実装 const handlePageChange = (newPage: number) => { if (newPage

    > 0 && newPage <= totalPages) { startTransition(() => { setItemsLocalDiff(new Map()); setCurrentPage(newPage); }); } }; 23 ページ移動時にlocalDiffを空にする。 複数のステート更新はバッチ化される ので動きとしては問題ない
  5. アイデア: 従属先を覚えておく localDiffがどのitemsに従属するのか、keyで表現。 function useLocalDiff(key: object) { const [itemsLocalDiff, setItemsLocalDiff]

    = useState<{ key: object; localDiff: Map<number, { description: string }>; }>({ key: {}, localDiff: new Map(), }); 26 従来のMapに加えて、どのオブジェクト にそのMapが紐づくのかを記憶
  6. アイデア: 従属先を覚えておく const localDiff = itemsLocalDiff.key === key ? itemsLocalDiff.localDiff

    : new Map(); return [ localDiff, updateDiff /* 後述 */, ] as const; 27 現在のkeyがlocalDiffに紐づいたkeyと 異なる場合は、 新しいkeyに紐づいたdiffが存在しない ので、空のMapを返す
  7. アイデア: 従属先を覚えておく function updateDiff(id: number, description: string) { setItemsLocalDiff((prev) =>

    { const newLocalDiff = prev.key === key ? new Map(prev.localDiff) : new Map(); newLocalDiff.set(id, { description }); return { key, localDiff: newLocalDiff, }; }); } 28 ステート更新のタイミングで最新のkeyを反映