昨天我們認識了什麼是 Redux,以及初步安裝及設定 Redux ,讓 Redux 保管的資料可以被子元件取得。
今天我們要繼續學習 Redux,從子元件內取得我們需要的資料。
要取得資料,需要使用useSelector
來獲取,功能就像是useContext
,裡面需要一個 callback function 來 return 我們需要的值:
import {useSelector} from 'react-redux';
const Counter = () => {
const value = useSelector(state => state.value)
return (
<div>
<h2>已經按了 {value} 次</h2>
<button>按我</button>
</div>
)
}
昨天已經寫過事件了,就是在設定 Reducer 時,比對action.type
,根據 type 來判斷相對應動作的部分。
const counterReducer = (state = initialState, action) => {
switch(action.type){
// 加入plus、minus action
case "plus":
return {value: state.value + 1};
case "minus":
return {value: state.value - 1};
default:
return state;
}
}
這邊要提醒一下,由於 React 偵測是否要 re-render 的方式是觀察物件的 reference 有沒有變化,而不是值,因此若只是單純的使用:
case "plus":
state.value += 1;
return state;
這樣的情況下,由於 reference 沒有改變,React 並不會因應變化 re-render。
因此,我們必須重新賦值,也就是重新給一個object:
case "plus":
return {value: state.value + 1}
重新賦值後的物件的 reference 不同,因此 React 可以偵測到變化而 re-render。
那樣如何更動 state 呢?這時候就需要使用到useDispatch
來傳遞指令給reducer。上面我們已經建立好action.type
的條件判斷了,接著我們要來建立要傳送的 action:
const action = {
type: "plus",
}
這樣當 reducer 接受到指令,便會執行相對應動作。
不過每一次都要重新寫一次物件很麻煩,因此可以把它寫成 function:
const plusValue = ()=>{
type: "plus"
}
const minusValue = () => {
type: "minus"
}
只有 action 是不行的,這個 action 還沒被指派給 store,因此,我們需要使用 useDispatch
,來幫助我們指派 action。
import {useDispatch} from 'react-redux';
const dispatch = useDispatch();
取得dispatch
後,就可以使用dispatch()
去傳遞 action:
import {useSelector, useDispatch} from 'react-redux';
const Counter = () => {
const value = useSelector(state => state.value)
const dispatch = useDispatch();
return (
<div>
<h2>已經按了 {value} 次</h2>
<button onClick={()=> dispatch(plusValue())}>按我</button>
</div>
)
}
這樣畫面就會因應按鈕而變化了。
如果想要傳入值來改變 state,只需要在 action 物件中加上payload
來放入要傳入的物件即可。
先將 reducer 改一下:
const counterReducer = (state = initialState, action) => {
switch(action.type){
// 加入plus、minus action
case "plus":
return {value: state.value + action.payload.value};
case "minus":
return {value: state.value - action.payload.value};
default:
return state;
}
}
接著更動 action 的 function:
const plusValue = (value)=>{
return {
type: "plus",
payload: {
value,
}
}
}
在元件中加個 input 和 state 來取得要更動的值,並傳入 dispatch:
const Counter = ()=>{
const [number, setNumber]=useState(0);
const count = useSelector(state=> state.value);
const dispatch = useDispatch();
return (
<div>
<h1>Result : {count}</h1>
<input type="number" onChange={e=> setNumber((Number(e.target.value)))}/>
<button onClick={()=> dispatch(plus(number))}>按我</button>
</div>
)
}
這樣畫面就會因應輸入的值做加法計算,並更動 Reducer 的 state了 !
參考資料
Day13 | React 的快樂小夥伴 - Redux 事件處理篇
[week 23] 淺談 Redux:狀態管理是一門學問
Getting Started with Redux - Redux