State Hooks useReducer
在上一节的最后,简单说明了一下有多个 state
时,我们如何定义。
根据描述,如果 state
非常多时,就需要定义很多的 useState
, 所以我们引入 useReducer
。
定义
const [state, dispatch] = useReducer(reducer, initialArg, init);
实例
import React, { useReducer } from 'react';
const initialState = {
count: 0,
value: null
}
export default () => {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<div className="example-rooter">
<p>当前记数为:{state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
<input value={state.value} onChange={(e) => dispatch({ type: 'value_Changed', value: e.target.value })} />
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
const reducer = (state, action) => {
const _state = { ...state };
switch (action.type) {
case 'increment':
_state.count = state.count + 1;
break;
case 'decrement':
_state.count = state.count - 1;
break;
case 'value_Changed':
_state.value = action.value;
break;
case 'reset':
_state.count = state.value;
break;
default:
throw new TypeError();
}
return _state;
}
和 useState
一样,我们通过 react
引入 useReducer
, 需要单独定义一个 reducer
函数,我们惊奇的发现,这个 reducer
函数与我们之前熟悉的 Redux
中的 reducer
长的几乎一模一样,所以不再详解示例。
下面解释一下这个 useReducer
:
state
: 从useReducer
中解构出这个参数,这个参数就是useReducer
第一个参数reducer
函数返回的值。dispatch
: 和state
一样,由useReducer
解构出。其作用和Redux
中的dispatch
相似。通过action
来设置一个state
的值。reducer
:useReducer
的第一个参数,是对state
操作的函数,该函数有两个参数构成 ——state
和action
, 与Redux
中的reducer
一致。函数返回一个immutable state
, 而且只返回每一个return
的当前数据,不会将所有的state assign
后都返回。 所以如果直接修改state
参数,然后返回当前state
是不生效的。initialArg
: 顾名思义,初始化的state
值。我们建议,每一个 state 都应该初始化。init
:lazy initial state
, 是一个函数,通过函数的方式初始化一个state
值。再次强调,如果
dispatch
中return
一个相同的state
(reducer
参数中的state
),React
不再渲然children
或者触发effects
事件。因为 React 使用的是Object.is
算法来比较dispatch
返回的state
的。