ReactHook之useReducer结合useContext完成大项目

212 阅读3分钟

我正在参加「掘金·启航计划」

本文将介绍useReducer的用法,也会大量引用React官方-useReducer的讲解思路,最后结合useContext实现一个小demo,这个demo直接复制就可以搭建一个又大又完整项目。

首先useReducer是啥玩样儿呢? 官方说:useState的替代方案。

如果认真看完本文你会发现,这都可以算是一种技术了,在他们眼里居然只是小小的替代方案。

使用场景:在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。

使用场景官方解释也甚是清晰,如果你了解过redux的话就可以很容易理解,总之就是复杂多变情况下就可以使用useReducer去解决问题。useReducer的使用方法和redux极其相似,所以我说这是一种技术。

const [state, dispatch] = useReducer(reducer, initState , init)

useReducer的三个穿参,第一个参数:reducer函数。第二个参数:初始化的state。第三个参数:initialAction要执行的初始动作。返回值为最新的state和dispatch函数。useReducer的使用方法和redux极其相似,所以我说这是一种技术。

官方文档就有一个useReducer的小demo,代码就不搬了可以移步去官方文档,其实看不看无所谓的看了更容易理解,看了的话你会发现useReducer的使用方法和redux极其相似,所以我说这是一种技术(不说这句话了,不然有点像在CPU你)。

接下来简单的封装一下useReducer需要的第一个参数和第二个参数(第三个一般情况不大用得到所以先不管了)。

1.创建reducer.js文件,封装useReducer需要的第一个参数和第二个参数

// reducer.js
export const initialData = {
    loading: false,
    user: []
}
export const reducer = (state = initialData, action) => {
    switch (action.type) {
        case 'LOADING_STATUS':
            return { ...state, loading: action.data }
        case 'SET_USERINFO':
            return { ...state, user: action.data }
        .
        .
        .
        default:
            break;
    }
}

2.创建store.js文件, 这里要createContext创建一个context对象然后将useReducer返回的value注入Provide,然后useContext去获取context

// store.js
import React, { useReducer, useContext } from 'react'
import { reducer, initialData } from './reducer.js'

const RootContext = React.createContext(initialData)
const setProvider = Component => props => {
    const value = useReducer(reducer, initialData)

    return (
        <RootContext.Provider value={value}>
            <Component {...props} />
        </RootContext.Provider>
    )
}
const useStore = () => {
    return useContext(RootContext);
}

export { setProvider, useStore }

3.创建index.js文件,初始化store及其使用

import React, { useState, useEffect } from 'react'
import { setProvider, useStore } from './store'
import axios from 'axios'

// 这是最外层的Layout
function MyLayout(props) {
    const [store, dispatch] = useStore()
    const { loading, user } = store
    
    useEffect(() => {
        getUserData({});
    }, [])
    
    const getUserData = (data) => {
        dispatch({
            type: 'LOADING_STATUS',
            data: true
        })
        axios.get(...).then(result => {
            dispatch({
                type: 'SET_USERINFO',
                data: result.data 
            })
             dispatch({
                type: 'LOADING_STATUS',
                data: false
            })
        })
        // ...
    }
    
    return <Spin loading={loading}>
        <div>{user.name || '--'}</div>
        {props.children ...}
    </Spin>
    
}

export default setProvider(MyLayout)

至此就是文字的核心内容了,使用好useReducer可以有效的避免经常使用回调函数去更新数据,让项目减负。

内容也没多少,但也可以慢慢领悟了一些react哲学,对于创建react项目还是有一些帮助的。

感谢观看,阿泽祝大家身体健康,万事如意。