iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0

昨天我們認識了什麼是 Redux,以及初步安裝及設定 Redux ,讓 Redux 保管的資料可以被子元件取得。
今天我們要繼續學習 Redux,從子元件內取得我們需要的資料。

useSelector

要取得資料,需要使用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。

action

那樣如何更動 state 呢?這時候就需要使用到useDispatch來傳遞指令給reducer。上面我們已經建立好action.type的條件判斷了,接著我們要來建立要傳送的 action:

const action = {
    type: "plus",
}

這樣當 reducer 接受到指令,便會執行相對應動作。
不過每一次都要重新寫一次物件很麻煩,因此可以把它寫成 function:

const plusValue = ()=>{
    type: "plus"
}

const minusValue = () => {
    type: "minus"
}

useDispatch

只有 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


上一篇
[Day17] 用 React 讓網站動起來:認識 redux
下一篇
[Day19]用 React 讓網站動起來:React-router
系列文
用React讓網頁動起來: React基礎與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言