React从0开始(八):React Hooks之useReducer

372 阅读2分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

在上一篇文章里我们学了useEffect,我们可以利用useEffect在组件渲染时触发副作用(还能够限制副作用的触发条件),还能够用多个useEffect将副作用关注点分离,避免把多个副作用堆在一个组件的生命周期里。今天我们一起来学习一下另外一个React Hooks——useReducer

一、Reducer复习

在之前的文章里,我们有接触过Reducer,它是Redux里的一个重要部分,在Redux里我们主要这么使用Reducer

  1. 创建Reducer函数,入参为初始StateAction,内部通过Action.type定义不同逻辑,最终返回新的State
  2. 利用Reducer作为参数进行React.createStore,得到Store实例
  3. 在使用Store的组件中导入Store实例对象
  4. 使用时,调用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来处理获得

使用流程:

  1. 创建Reducer函数,按照上文编写Reducer逻辑(Reducer函数中的State参数可以在内部逻辑中作为上一个State参与逻辑处理)
  2. 新建一个State对象作为初始State
  3. Reducer函数与State对象作为参数传入useReducer,并通过解构来接收useReducer钩子返回的State与用于派发更新的setReducer函数
  4. 如果需要进行派发,则调用: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>
    )
}