😎
redux-toolkitでdispatch書きまくり問題をなんとかする
概要
redux-toolkitって良いですよね。
ただ、コード書いてると「dispatchって書きまくりじゃね?」と思ったので、
なんとかしたいと思います。
環境作成
Create React Appでredux-toolkitかつtypescriptのテンプレートがあるので、
それを使っていきます。
npx create-react-app redux-toolkit-app --template redux-typescript
yarn start
してみると、こんな感じ
よくあるカウンターアプリですね。
カスタムフックを作る
別ファイル作った方が良いような気もするんですが、
counterSlice.ts
に以下を追加します。
src/features/counter/counterSlice.ts
export const useCounter = () => {
const dispatch = useDispatch();
const { actions } = counterSlice;
const increment = () => dispatch(actions.increment());
const decrement = () => dispatch(actions.decrement());
const incrementByAmount = (payload: number) =>
dispatch(actions.incrementByAmount(payload));
const incrementAsync = (amount: number) => {
setTimeout(() => {
dispatch(actions.incrementByAmount(amount));
}, 1000);
};
return { increment, decrement, incrementByAmount, incrementAsync };
};
呼び出し側のコード修正
src/features/counter/Counter.tsx
export function Counter() {
const count = useSelector(selectCount);
- const dispatch = useDispatch();
+ const {
+ increment,
+ decrement,
+ incrementByAmount,
+ incrementAsync,
+ } = useCounter();
const [incrementAmount, setIncrementAmount] = useState('2');
return (
<button
className={styles.button}
aria-label="Increment value"
- onClick={() => dispatch(increment())}
+ onClick={increment}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
- onClick={() => dispatch(decrement())}
+ onClick={decrement}
>
-
</button>
className={styles.textbox}
aria-label="Set increment amount"
value={incrementAmount}
onChange={(e) => setIncrementAmount(e.target.value)}
/>
<button
className={styles.button}
- onClick={() =>
- dispatch(incrementByAmount(Number(incrementAmount) || 0))
- }
+ onClick={() => incrementByAmount(Number(incrementAmount) || 0)}
>
Add Amount
</button>
<button
className={styles.asyncButton}
- onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
+ onClick={() => incrementAsync(Number(incrementAmount) || 0)}
>
Add Async
</button>
</div>
</div>
);
}
感想
とりあえず、コンポーネントのコードからはdispatchを取り除く事ができました。
この例だとイマイチかもしれないんですが、別コンポーネントからもincrementしたい時に、
dispatchせずともカスタムフック呼び出せば良いので、そっちのが良いかなという感じです。
コード
今回のコードはこちらに置きました。
Discussion