我试图了解使用 useState 钩子的哪种方式是更好的做法。请考虑以下两个简单 React 组件的示例:
多个 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;
一个 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;
哪个选项会被认为更好?这里有什么我以后应该避免的错误/不良做法吗?
答案 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(...)
来合并剩余的状态