这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战
在上一篇文章里我们学了useEffect
,我们可以利用useEffect
在组件渲染时触发副作用(还能够限制副作用的触发条件),还能够用多个useEffect
将副作用关注点分离,避免把多个副作用堆在一个组件的生命周期里。今天我们一起来学习一下另外一个React Hooks
——useReducer
一、Reducer
复习
在之前的文章里,我们有接触过Reducer
,它是Redux
里的一个重要部分,在Redux
里我们主要这么使用Reducer
:
- 创建
Reducer
函数,入参为初始State
与Action
,内部通过Action.type
定义不同逻辑,最终返回新的State
- 利用
Reducer
作为参数进行React.createStore
,得到Store
实例 - 在使用
Store
的组件中导入Store
实例对象 - 使用时,调用
Store.dispatch( { type:"example" } )
进行派发事件即可
//Store.js
const Reducer = ({ content:"初始State" },action)=>{
switch(action.type){
case "A" : return { content:"A" }
case "B" : return { content:"B" }
default : return { content:"C" }
}
}
const Store = React.createStore(Reducer);
export default Store;
//A.js
import Store from "./Redux/Store.js"
class A extends React.Component {
render() {
return (
<div onClick={ ()=>{ Store.dispatch( {type:"A"} ) } }>Click Me</div>
)
}
}
二、useReducer
学习
useReducer
的使用:
传入参数:
- 参数一:
Reducer
函数 - 参数二:
Action
返回内容: - 返回一个数组
- 数组第一项:当前
State
- 数组第二项:用于派发的函数,传入
Action
,相当于Redux
中的Store.dispatch( {type:"example"} )
使用场景: State
逻辑复杂且有多个子值- 下一个
State
需要依赖上一个State
来处理获得
使用流程:
- 创建
Reducer
函数,按照上文编写Reducer
逻辑(Reducer
函数中的State
参数可以在内部逻辑中作为上一个State
参与逻辑处理) - 新建一个
State
对象作为初始State
- 将
Reducer
函数与State
对象作为参数传入useReducer
,并通过解构来接收useReducer
钩子返回的State
与用于派发更新的setReducer
函数 - 如果需要进行派发,则调用:
setReducer( {type:"example"} )
来进行Action
派发,State
会进行更新
//初始化State
const initialState = { content:"init" }
//定义Reducer
const Reducer = (state,action) => {
switch(action.type){
case "A" : return { content:"A" }
case "B" : return { content:"B" }
default : return { content:"C" }
}
}
function showExampleA() {
//使用useReducer并接收State与setReducer
let [state, setReducer] = useReducer(Reducer,initialState)
//State的使用与Action派发
return (
<div>
<h1>{state.content}</h1>
<button onClick={ ()=>{ setReducer( {type:"A"} ) } }>Click Me</button>
</div>
)
}
另外,上文还有提到我们可以通过上一个State
来进行下一个State
处理的逻辑,我们一起来看一下:
//初始化State
const initialState = { count:0 }
//定义Reducer
const Reducer = (state,action) => {
switch(action.type){
case "one" : return { content:state.count+1 }
case "two" : return { content:state.count+2 }
default : return { content:state.count+3 }
}
}
function showExampleA() {
//使用useReducer并接收State与setReducer
let [state, setReducer] = useReducer(Reducer,initialState)
//State的使用与Action派发
return (
<div>
<h1>{state.count}</h1>
<button onClick={ ()=>{ setReducer( {type:"one"} ) } }>Click Me To Add 1</button>
<button onClick={ ()=>{ setReducer( {type:"two"} ) } }>Click Me To Add 2</button>
<button onClick={ ()=>{ setReducer( {type:""} ) } }>Click Me To Add 3</button>
</div>
)
}