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

Zustandを用いた実践的状態管理

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Nokogiri Nokogiri
July 17, 2025
760

 Zustandを用いた実践的状態管理

Avatar for Nokogiri

Nokogiri

July 17, 2025
Tweet

More Decks by Nokogiri

Transcript

  1. 1

  2. 7

  3. 1. Actions に状態更新ロジックを集約する const useStoreStockDialogStore = create<StoreStockDialogStore>()((set) => ({ actions:

    { updateStoreStockReason: (reason) => { set((state) => ({ ...state, // プライマリ状態の更新 storeStockInfoFormValues: { ...state.storeStockInfoFormValues, storeStockReason: reason, // 他の状態への副作用 counterPartyId: INITIAL_FORM_VALUES.counterPartyId, counterPartyName: INITIAL_FORM_VALUES.counterPartyName, }, stockOperationConfig: { ...state.stockOperationConfig, counterParty: null, }, })); }, }, })); 10
  4. 2. セレクターによる効率的な状態参照 // selectors.ts export const selectFeeAmount = (state: StoreStockDialogStore)

    => state.storeStockInfoFormValues.feeAmount; // Component const feeAmount = useStoreStockDialogStore(selectFeeAmount); 状態の参照を一箇所に集約 Stateのデータ構造を変えてもコンポーネント側に影響を出さない 純粋関数なのでテストしやすい 11
  5. 3. useShallow を使った配列への浅い参照 const selectMedicineIds = (state: StoreStockDialogStore) => state.medicineInfoList.map((i)

    => i.medicineId); function MedicineList() { const ids = useStoreStockDialogStore(useShallow(selectMedicineIds)); return ( <ul> {ids.map((id) => ( <MedicineListItem key={id} medicineId={id} /> ))} </ul> ); } 配列の内容が変わらなければ再描画を防ぐ。パフォーマンスの向上 createSelector でも代替可能 12
  6. 4. 末端コンポーネントでの状態参照 function MedicinePrice() { const medicinePrice = useStoreStockDialogStore(selectMedicinePrice); return

    ( <input type="text" value={medicine.price} /> ) } 必要な状態のみを参照 不要な再描画を防ぐ 13
  7. 5. Store のライフサイクル管理 // StoreProvider.tsx export const StoreProvider = ({

    children }: { children: ReactNode }) => { const storeRef = useRef<StoreApi<StoreStockDialogStore>>(); if (!storeRef.current) { storeRef.current = createStoreStockDialogStore(); } return ( <StoreContext.Provider value={storeRef.current}> {children} </StoreContext.Provider> ); }; Initialize state with props React コンポーネントのライフサイクルと連動 Stateの破棄漏れを防ぐ 14
  8. 6. immer を利用した安全な更新 const useStore = create<Store>()( immer((set) => ({

    nested: { value: 0 }, actions: { updateNested: (value) => { set((state) => { state.nested.value = value; // 直接代入可能 }); }, }, })) ); 不変性を保ちながら直感的な更新 バグの減少 15
  9. 17

  10. 18

  11. 20