如何使用useReducer代替useState?

Dha*_*r S 4 reactjs react-hooks use-reducer

您好,我的初始状态为空对象,

let [value,setValue] = useState({});

function onSubmit(){
  setValue({"new Object"})
}
Run Code Online (Sandbox Code Playgroud)

并在单击按钮时更新它。有什么方法可以在 useReducer 中实现这种情况,而且在这里我想创建一个新状态而不是改变它。非常感谢您的帮助或建议。

jpa*_*vel 5

两个钩子都定义了一个初始状态并返回一个 setter 和一个 getter 来处理该状态:

  [value,fn] = useReducer(...); // or useState(...);
Run Code Online (Sandbox Code Playgroud)

但是,在上面的代码片段中, 的行为fnuseReducerto不同useState。另外,useReducer需要 2 个参数,而useState只需要 1 个。基本上:

  • useReducer:需要 2 个参数,(a) 一个函数(称为减速器函数),以及 (b) 状态的初始值。fn每当您使用某个值调用时,都会调用reducer函数来修改状态。并且传递给的值fn将传递给reducer函数(作为第二个参数)。

  • useState:仅期望 1 个参数,即状态的初始值。它只会将状态替换为作为参数传递的值fn(可选地,您也可以将函数传递给fn,该函数接收当前状态作为参数并返回新状态)。

示例useState

const { useState } = React;

const App = () => {
  const initialState = { called: false, name: 'Jane' };
  const [value, setValue] = useState(initialState);
  const replaceState = () => {
    setValue({ 
      called: true, 
      fullName: `${value.name ? value.name : 'Just'} Fonda` 
    });
  }
  return (
    <div className="App">
      <button onClick={replaceState}>Replace Name</button>
      <button onClick={(e) => setValue(initialState)}>Reset</button>
      <pre>{JSON.stringify(value)}</pre>
      {value.called 
       ? <pre>Notice that there's no 'name' attribute anymore</pre> 
       : null}
    </div>
  );
}

ReactDOM.render(<App />,root);
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

示例useReducer

reducer您必须构建一个将修改状态的函数(the )。该函数必须接收 2 个参数:实际状态和修改状态所需的任何值。

此外,该函数必须返回一个React 将设置为新状态的值。

如果您曾经使用过 redux 模式,那么您一定对这种行为很熟悉。因此,如果您像每个人一样想要坚持 redux 模式,请用作action减速器函数的第二个参数的名称(将用于修改状态)。它将是一个包含 2 个属性的对象:typepayload

减速器内部的逻辑处理操作,通过使用type(字符串)来决定如何使用(任何)修改状态payload。减速机内部装有减速机的情况并不罕见switch-case。因此,让我们遵循传统并使用这种类似 redux 的模式构建一个减速器。

const { useReducer } = React;

// Notice the two parameters of the reducer:
//   state: current state
//   payload: object with the shape {type: string, payload: any}
// Also, notice that the reducer MUST return a value to be used
//   as the new state. Remember that if you return nothing
//   javascript will return undefined
const reducer = (state, action) => {
  switch(action.type) {
    case 'inc': return state + action.payload;
    case 'dec': return state - action.payload;

    // for any other type, return the current state
    default: return state;
  }
}

const App = () => {
  // specify the reducer and an initial value for the state
  const [value, setValue] = useReducer(reducer, 0);

  const inc = (e) => setValue({type: 'inc', payload: 1});
  const dec = (e) => setValue({type: 'dec', payload: 1});

  return (
    <div className="App">
      <button onClick={inc}>Increment</button>
      <button onClick={dec}>Decrement</button>
      Counter:{value}
    </div>
  );
}

ReactDOM.render(<App />,root);
Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

最后附注,setValue我在上面的代码片段中使用的名称甚至与useReducer. 更常见的称呼是dispatch