【问题标题】:Using React Hooks with more than one Key/Value Pair in State Object在状态对象中使用具有多个键/值对的 React Hooks
【发布时间】:2019-12-09 19:41:04
【问题描述】:

我想知道最好的方法是在Functional Component 中为state 定义多个key/value 对。

在课堂上我会像State一样初始化

this.state = {
    first: 'foo',
    second: 'bar'
};

更新State我打电话

this.setState({
    first: 'foobar'
    second: 'barfoo'
});

现在使用React Hooks,我像这样初始化State

const [first setfirst] = useState('foo');
const [second, setSecond] = useState('bar');

更新State我打电话

setFirst = 'foobar';
setSecond = 'barfoo';

但是,恕我直言,这并不理想。每次我想向State object 添加一个新的key/value 对时,我都必须重写const [x, setX] = useState(...);。样板。我还必须始终牢记x 的“setter”名称,即setX。如果State object 增长,那将变得一团糟。

如果我能简单地打电话就更好了

setState(first: 'foobar', second: 'barfoo');

但我不确定如何正确初始化State object/最好的方法是什么。

【问题讨论】:

  • 您找到了最好的方法吗?我想避免在使用 setState 时重新渲染多个子组件
  • @UMR 使用接受的答案。
  • 但你忘了接受答案...我使用 React.memo 和 useReducer @Stophface 的组合
  • @UMR 有一个接受的答案,有七个赞成票……来自 Monika Mangal 的那个。 Alireza HI 提供的答案也有效……仔细观察。我觉得你想达到的和我想做的不一样。

标签: javascript reactjs


【解决方案1】:

使用对象作为初始值

您可以使用javascript object 作为您的值。 通过这种方式,您可以将更多变量放在您的对象和一个地方。 所以你的代码如下:

const [example, setExample] = useState({first:'foobar', second:barfoo''});

然后你可以像这样更新它:

setExample({...example,first:'new foobar'})
setExample({...example,second:'new foobar second'})

这种类型的setting 正在解构您以前的值,并用旧值替换您的新值。

使用此对象,您只需将新的property 添加到example 的初始化以及您需要设置它的位置。

作为一个复杂的示例,您可以访问此链接:

React Hooks useState() with Object


注意(更新变量)

如果您只是使用{first:'new foobar'} 更新它并且不在您的属性中包含second,您可能会丢失第二个的旧值。所以使用...example 来获得second 的旧值。

【讨论】:

    【解决方案2】:

    你可以自己做一个钩子来做这个!

    function useMultipleStates() {
        const [first setFirst] = useState('foo');
        const [second, setSecond] = useState('bar');
    
        const setState = (f, s) => {
            setFirst(f);
            setSecond(s);
        }
    
        return {
            first,
            second,
            setState,
        }
    }
    

    您可以根据自己的需要进行调整,但如果应该让您知道如何做到这一点。

    【讨论】:

    • 那是更多样板、开销、错误加载。
    【解决方案3】:

    您可以使用 useState 设置整个对象,如下所示 -

    const [stateObj, setStateObj] = useState({first:'foobar', second:'barfoo'});
    

    然后更新状态 -

    setStateObj({first:'foobarnew', second:'barfoonew'})
    

    【讨论】:

    • 如果您没有像这样设置所有状态,请不要忘记传播state。旧this.setState() 更新相关属性并将更改的属性与状态合并,但使用钩子时,状态总是被覆盖。
    【解决方案4】:

    来自 React 文档:当您有涉及多个子值的复杂状态逻辑或下一个状态取决于前一个状态时,useReducer 通常比useState 更可取。 useReducer 还允许您优化触发深度更新的组件的性能,因为您可以向下传递调度而不是回调。

    const initialState = { first: '', second: '' };
    
    function reducer(state, action) {
      switch (action.type) {
        case 'doFirst':
          return {...state, first: 'newFirst' };
        case 'doSecond':
          return {...state, second: 'newSecond' };
        default:
          throw new Error();
      }
    }
    
    function Component() {
      const [state, dispatch] = useReducer(reducer, initialState);
      return (
        <>
          {state.first}
          {state.second}
          <button onClick={() => dispatch({type: 'doFirst'})}></button>
          <button onClick={() => dispatch({type: 'doSecond'})}></button>
        </>
      );
    }
    

    【讨论】:

      【解决方案5】:

      我建议使用减速器挂钩。 React 官方网站说如果你有复杂的状态,宁愿去 userReducer 钩子。

      
      
      const initialState = {
      first: 'foo',
      second: 'bar'
      };
      
      function reducer(state, action) {
        switch (action.type) {
          case 'updateFirst':
            return {...state, first: 'fooBar' };
          case 'updateSecond':
            return {...state, second: 'barfoo' };
          case 'updateBoth':
            return {...state, second: 'barfoo',first: 'fooBar' };
          default:
            throw new Error();
        }
      }
      
      function Component() {
        const [state, dispatch] = useReducer(reducer, initialState);
        return (
          <>
            {state.first}
            {state.second}
            <button onClick={() => dispatch({type: 'updateFirst'})}>UpdateFirst</button>
            <button onClick={() => dispatch({type: 'updateSecond'})}>UpdateSecond</button>
            <button onClick={() => dispatch({type: 'updateBoth'})}>UpdateBoth</button>
          </>
        );
      }
      
      
      

      代码:https://codesandbox.io/s/busy-rosalind-9oiow

      【讨论】:

      • 对于这么简单的事情来说太多样板文件了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      相关资源
      最近更新 更多