Sean's Blog

An image showing avatar

Hi, I'm Sean

這裡記錄我學習網站開發的筆記
歡迎交流 (ゝ∀・)b

LinkedInGitHub

React Redux with Functional Components

本文介紹 React Redux 於 Functional Components 的使用。

useSelector hook

A hook to access the redux store's state, and manage the subscription behind the scenes.

useSelector 會監控 Redux 特定狀態的更動,有點類似 Vuex 中 computed 計算屬性的感覺。

1import { useSelector } from 'react-redux';
2
3const Counter = () => {
4  // 取出 store 裡面特定的 state,只取得需要的 state!
5  const counter = useSelector((state) => state.counter);
6
7  return (
8    <main>
9      <div>{counter}</div>
10    </main>
11  );
12};
13
14export default Counter;
15

當 Redux Store 更新時,使用 counter 的 Component 也會一起被更新(重新評估、執行),因為這樣才能確保接收 Redux 最新的 state 喔。

useDispatch hook

A hook to access the redux dispatch function.

useDispatch 提供 dispatch 函式:const dispatch = useDispatch()

1import { useDispatch } from 'react-redux';
2
3const Counter = () => {
4  const dispatch = useDispatch();
5
6  const incrementHandler = () => {
7    dispatch({ type: 'INCREMENT' });
8  };
9
10  const decrementHandler = () => {
11    dispatch({ type: 'DECREMENT' });
12  };
13
14  return (
15    <main>
16      <button onClick={incrementHandler}>Increment</button>
17      <button onClick={decrementHandler}>Decrement</button>
18    </main>
19  );
20};
21
22export default Counter;
23

給 Actions 物件加上更多 Payloads

瞭解 Redux 基本的使用後,我們繼續往下看一些比較深入而且實用的功能吧!

當我們 Dispatch 一個 Action 物件時,Payload 裡面除了 type 我們還可以放更多內容,像是定義 amount,讓按鈕可以一次加上指定的數量。

1// Counter Component
2const Counter = () => {
3  const increaseHandler = () => {
4    dispatch({ type: 'INCREASE', amount: 5 });
5  };
6  // return jsx...
7};
8
9// Redux Reducer Function
10const counterReducer = (state = { counter: 0 }, action) => {
11  if (action.type === 'INCREASE') {
12    return { counter: state.counter + action.amount };
13  }
14};
15

如果有多個 State 記得一起更新

進行 Dispatch Action 更新 State 物件時,就算有些 State 我們在 Action 中不會去改動到,但還是需要把它們寫進 return 的物件裡,因為這個 return 的物件是會取代掉原本的整個 State 物件的。

  • 重點一:return 的 State 不是合併,是整個「覆寫」!
  • 重點二:千萬不要直接改變 (Mutate) 現有的狀態,也就是不能直接對 State 做改變,正確的做法是在進行操作後,再去 return 整個新的 State 物件。
1if (action.type === 'INCREASE') {
2  // Never mutate state!!!
3  // state.counter++;
4  // return state;
5  return {
6    counter: state.counter + action.amount,
7    showCounter: state.showCounter, // 不更動
8  };
9}
10
11if (action.type === 'TOGGLE') {
12  return {
13    counter: state.counter, // 不更動
14    showCounter: !state.showCounter,
15  };
16}
17

回顧

看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到…

  • useSelector hook
  • useDispatch hook

References