哪个更有效:对经常更新的对象使用多个 useState 钩子还是一个 useState?

时间:2021-07-27 05:41:23

标签: reactjs react-hooks use-state

我试图了解使用 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;
    

哪个选项会被认为更好?这里有什么我以后应该避免的错误/不良做法吗?

3 个答案:

答案 0 :(得分:2)

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

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

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

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

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

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

因此,如果您的状态在逻辑上应该被分组在一起并且不是非常嵌套,那么您可以将其保持在一起。

hooks FAQ 中有一个 section,可以直接回答这个问题。直接来自文档:

<块引用>

我们建议根据哪些值倾向于一起改变,将状态拆分为多个状态变量。

答案 1 :(得分:1)

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

这是一个关于使用单个或多个变量的链接,您也可以参考它。

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

我想建议您如果要使用 single useState 然后尝试编写如下代码:

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

答案 2 :(得分:0)

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