- useReducer
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法,跟Redux类似。
在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</div>
);
}
const [state, dispatch] = useReducer(reducer, initialState),useReducer会接收两个参数
- 第一个参数是一个reducer
- 第二个参数是state初始的默认值
并返回两个参数
- 当前的state值
- dispatch方法,该方法可以发布一个事件来更新state
什么是reducer?
简单来说 reducer是一个函数(state, action) => newState:接收当前应用的state和触发的动作action,计算并返回最新的state。例:
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
- useReducer()和useContext()实现Redux效果
如不熟悉useContext可查看之前发布的文章: react Hook useContext()
import React, { createContext, useContext, useReducer } from 'react'
// 定义初始化值
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
// 创造一个上下文
const context = createContext(null);
function A() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<context.Provider value={{ state, dispatch }}>
<div>这是A组件</div>
<B></B>
</context.Provider>
)
}
function B() {
const { state, dispatch } = useContext(context)
return (
<div>
这是B组件: {state.count}
<C></C>
</div>
)
}
function C() {
const { state, dispatch } = useContext(context)
return (
<div>
这是C组件: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>-</button>
<button onClick={() => dispatch({type: 'decrement'})}>+</button>
</div>
)
}