哪个更有效:对经常更新的对象使用多个 useState 挂钩或一个 useState?

Which is more efficient: use of many useState hooks or one useState for often updated object?

我正在尝试了解哪种使用 useState 钩子的方式是更好的做法。请考虑这两个简单的 React 组件示例:

  1. 多个 useState 挂钩

    const Cake = () => {
        const [topping, setTopping] = useState('');
        const [icing, setIcing] = useState('');
        const [fruit, setFruit] = useState('');
        const [base, setBase] = useState('');
        const [cake, setCake] = useState({topping: '', icing: '', fruit: '', base: ''});
    
        const createCake = () => {
            setCake({
                topping: topping,
                icing: icing,
                fruit: fruit,
                base: base
            });
            console.log(cake);
        }
    
        return (
            <div>
                <p>Choose from possible toppings:</p>
                <Select options={toppings} onChange={e => setTopping(e.target.value)} value={topping}/>
                <p>Choose from possible icings:</p>
                <Select options={icings} onChange={e => setIcing(e.target.value)} value={icing}/>
                <p>Choose from possible fruits:</p>
                <Select options={fruits} onChange={e => setFruit(e.target.value)} value={fruit}/>
                <p>Choose from possible bases:</p>
                <Select options={bases} onChange={e => setBase(e.target.value)} value={base}/>
    
                    <button onClick={createCake}>Create</button>
                </div>
            );
        }
    
        export default Cake;
    
    
  2. 一个useState钩子,但是整个对象的所有属性都更新了多次

    从 'react' 导入 React,{useState};

     const Cake = () => {
         const [cake, setCake] = useState({topping: '', icing: '', fruit: '', base: ''});
    
         const setTopping = (e) => {
             setCake({
                 topping: e.target.value,
                 icing: cake.icing,
                 fruit: cake.fruit,
                 base: cake.base
             });
         };
    
         const setIcing = (e) => {
             setCake({
                 topping: cake.topping,
                 icing: e.target.value,
                 fruit: cake.fruit,
                 base: cake.base
             });
         };
    
         const setBase = (e) => {
             setCake({
                 topping: cake.topping,
                 icing: cake.icing,
                 fruit: cake.fruit,
                 base: e.target.value
             });
         };
    
         const setFruit = (e) => {
             setCake({
                 topping: cake.topping,
                 icing: cake.icing,
                 fruit: e.target.value
                 base: cake.base
             });
         };
    
         const createCake = () => {
             console.log(cake);
         };
    
         return (
             <div>
                 <p>Choose from possible toppings:</p>
                 <Select options={toppings} onChange={setTopping}/>
                 <p>Choose from possible icings:</p>
                 <Select options={icings} onChange={setIcing} value={icing}/>
                 <p>Choose from possible fruits:</p>
                 <Select options={fruits} onChange={setFruit} value={fruit}/>
                 <p>Choose from possible bases:</p>
                 <Select options={bases} onChange={setBase} value={base}/>
    
                 <button onClick={createCake}>Create</button>
                 </div>
             );
         }
    
         export default Cake;
    

这个选项中哪个更好?这里有什么 mistakes/bad 我以后应该避免的做法吗?

这取决于值如何变化。如果它们一起改变,则将它们放在一个变量中,如果不是,则拆分对象。

钩子的 setState 和 classes 的一个主要区别是: 对于 class 个组件 this.setState 自动合并状态对象。

this.setState({ topping: 'newTopping' });

但是在钩子中,你必须用一个新的状态变量替换状态变量并且没有合并。

这就是您会看到 spread operator ... 用于创建对象副本然后用 setState 替换对象的原因。

setCake(cake => { ...cake, topping : 'newTopping' });

所以如果你的状态在逻辑上应该被组合在一起并且不是很嵌套,你可以将它们放在一起。

hooks 常见问题解答中有一个 section,直接回答了这个问题。直接来自文档:

we recommend to split state into multiple state variables based on which values tend to change together.

您可以根据您的用例选择任何方法。但根据官方文档,建议将状态拆分为多个状态变量,根据哪些值趋向于一起变化。

这里有个link说的单变量或者多变量的使用你也可以参考

https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables

我建议如果你是单机useState,那么尝试写代码如下:

setCake((cake) => ({
  ...cake,
  fruit: e.target.value
}));

您可以使用其中任何一种方法来更新状态,但这最终取决于您的用例。在实际应用程序中,您会遇到这两种情况。 只需确保您使用的是哪种组件类型,即:class 或功能组件。 Class组件this.setState自动合并状态对象而功能组件需要spread operator(...)合并剩余状态