useReducer和useState都是用於资料状态管理的Hook,
那我该怎麽区分使用他们的时机呢?
useState
:
适合用於不受其他state影响的独立资料状态。
useReducer
:
适合用於受其他较多条件影响、复杂的资料状态。
我们多将 useReducer
和 context API
用来做全域共用state的管理,
透过ruducer函式里的判断条件来更新state,更方便集中管理逻辑复杂的state。
//App.js
import React, { useReducer } from 'react';
//我设资料初始值为物件,里面带两个之後要使用的值
const setValue = {
text: "黑色", color: 'black'
}
reducer
自定义判断资料更新的ruducer函式,有两个参数state、action可以使用,根据action条件的不同,决定返回的新state资料。
//自定义的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;
}
}
其中两个传入的参数为
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
这样点击更新资料後,我们就可以利用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 - 战略设计的目的
早起运动Day12 - 你不想动的点在哪里 《试错力》这本书,讲的是创新如何从无到有。 试错的重点有...
昨天介绍完使用相机拍照,今天会分享如何从相簿选取照片 成品: 拉一个 Button 、 ImageV...
此刻所发生的所有事,都是你之前选择的结果。 Everything that is happening...
隐私如浮云,多半用户即刻享受当下服务的快感解决需求,至於隐私就都化为浮云飘过视而无见,如同Day 2...
FrameLayout(帧布局) FrameLayout是布局当中最简单的一个, 在未设定的情况下,...