Day25 React useReducer - 另种管理state的方法

useReducer和useState都是用於资料状态管理的Hook,
那我该怎麽区分使用他们的时机呢?

useState
适合用於不受其他state影响的独立资料状态。

useReducer
适合用於受其他较多条件影响、复杂的资料状态。

我们多将 useReducercontext API 用来做全域共用state的管理,
透过ruducer函式里的判断条件来更新state,更方便集中管理逻辑复杂的state。


useReducer使用方法

第一步:引入useReducer

//App.js

import React, { useReducer } from 'react';

第二步:自定初始的State资料

//我设资料初始值为物件,里面带两个之後要使用的值
const setValue = {
  text: "黑色", color: 'black'
}

第三步:建立 reducer

自定义判断资料更新的ruducer函式,有两个参数state、action可以使用,根据action条件的不同,决定返回的新state资料。

  • state:使用seReducer()返回的的目前state状态()
  • action:利用useReducer中类似setState的资料更新函式 (dispatch) 带入的字串或物件,来判断资料更新逻辑。
//自定义的reducer函式
function reducer(state, action) {

//判断action等於dispatch带入的参数,我取里面的type值做更新判断
  switch (action.type) {
    case 'red':
      return {
        text: '红色', color: action.type
      }
    case 'blue':
      return {
        text: '蓝色', color: action.type
      }
    default:
      return state;
  }
}

第四步:在元件function内宣告使用useReducer

其中两个传入的参数为

  • reducer:
    第三步建立的reducer函式,让useReducer可以根据它返回正确要更新的资料。

  • setValue:
    第一步设立的初始资料格式。

//const [state, dispatch] = useReducer(reducer函式, 初始资料);

//照前面步骤的设定放入参数
const [state, dispatch] = useReducer(reducer, setValue);

而我们宣告的变数(可自订)分别是:

  • state:
    这里的state可以在jsx上用props传入子元件,或是搭配上上篇的context设定全域state。

  • dispatch:
    接收action参数的函式,我们会根据传入的action,带入第三步的ruducer做判断返回更新state给useReducer的state

第五步:使用dispatch传入条件做资料更新

这样点击更新资料後,我们就可以利用useReducer保存的state了,
在这边我们将state传入context做全域资料,让下两层的子元件使用。

function App() {

//
  const [state, dispatch] = useReducer(reducer, setValue);

  return (
    <div className="App">

		//点击按钮後使用dispatch传入action到ruducer函式做条件判断(action的值也可以用物件传入)
        <button onClick={() => dispatch({ type: 'red' })}>切到红色</button>
        <button onClick={() => dispatch({ type: 'blue' })}>切到蓝色</button>

			//将useReducer的state资料传入context
        <ContextState.Provider value={state}>
          <Child />
        </ContextState.Provider>
    </div >)

}

最後呈现的效果如下:


全部的程序码:

App.js

import React, { useReducer } from 'react';
import './App.css';
import { ContextState } from './context/ContextState.js'
import Child from './component/Child';

const setValue = {
  text: "黑色", color: 'black'
}

function reducer(state, action) {
  switch (action.type) {
    case 'red':
      return {
        text: '红色', color: action.type
      }
    case 'blue':
      return {
        text: '蓝色', color: action.type
      }
    default:
      return state;
  }
}

//元件function
function App() {

  const [state, dispatch] = useReducer(reducer, setValue);

  return (
    <div className="App">
     
        <button onClick={() => dispatch({ type: 'red' })}>切到红色</button>
        <button onClick={() => dispatch({ type: 'blue' })}>切到蓝色</button>
//context
        <ContextState.Provider value={state}>
          <Child />
        </ContextState.Provider>
    </div >)

}

export default App;

Child.js

import React from 'react';
import './Child.css'
import Grandson from './Grandson'

function Child() {

    return (
        <div className="App child-wrap" >
            <h4>Child元件用不到context</h4>
            <Grandson />
        </div>)

}

export default Child;

Grandson.js

import React, { useContext } from 'react';
import { ContextState } from '../context/ContextState'

function Grandson() {
    const getContext = useContext(ContextState)
    const styleColor = { color: getContext.color }

    return (
        <div className="App grandson-wrap" >
            Grandson元件使用Context
            <br />
            <div style={styleColor}>{getContext.text}</div>

        </div >)

}

export default Grandson;

<<:  30-25 之 DDD 战略设计 1 - 战略设计的目的

>>:  Day 25 - 介绍 OSPF

你不想动的卡点在...?

早起运动Day12 - 你不想动的点在哪里 《试错力》这本书,讲的是创新如何从无到有。 试错的重点有...

DAY 29『 从相簿选取照片( 有裁剪照片功能 ) 』ImagePicker - Part1

昨天介绍完使用相机拍照,今天会分享如何从相簿选取照片 成品: 拉一个 Button 、 ImageV...

此刻所发生的所有事,都是你之前选择的结果。

此刻所发生的所有事,都是你之前选择的结果。 Everything that is happening...

Day 11 已故用户的隐私设计

隐私如浮云,多半用户即刻享受当下服务的快感解决需求,至於隐私就都化为浮云飘过视而无见,如同Day 2...

Day-15 FrameLayout

FrameLayout(帧布局) FrameLayout是布局当中最简单的一个, 在未设定的情况下,...