我正在参加「掘金·启航计划」
本文将介绍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项目还是有一些帮助的。
感谢观看,阿泽祝大家身体健康,万事如意。