找到以下示例代码和屏幕截图。
两个问题:
counter
未正确更新,是否可以写类似setCounter((prev) => { return { counter: prev.counter - value || 1 }});
的东西?
setCounter(counter + value || 1)
的正确方法是什么
要工作,在缺少实际值的情况下使用1?
找到以下示例代码和屏幕截图。
const Counter = (props) => {
const [counter, setCounter] = useState(0);
const handleCounterChange = (action, value) => {
switch (action) {
case "+":
setCounter(counter + value || 1);
break;
case "-":
setCounter(counter - value || 1);
break;
default:
setCounter(counter + value || 1);
break;
}
};
return (
<div className={classes.Counter}>
<CounterOutput value={counter} />
<CounterControl
label="+"
clicked={() => handleCounterChange("+")}
/>
<CounterControl
label="-"
clicked={() => handleCounterChange("-")}
/>
<CounterControl
label="+ 5"
clicked={() => handleCounterChange("+", 5)}
/>
<CounterControl
label="- 5"
clicked={() => handleCounterChange("-", 5)}
/>
</div>
);
};
export default Counter;
答案 0 :(得分:2)
setCounter(counter + value || 1);
的问题在于,JS将尝试首先计算counter + value
然后布尔测试。因此,例如,如果您的counter
值为1
,并且减去了1
的值,则结果为0
,这是错误的,因此1
将保存为counter
的新值。这可能不是您想要的。
console.log(100 + undefined || 1); // expect 101 but result is 1
console.log(1 + -1 || 1); // expect 0 but result is 1
您可以将优先级分组,即counter + (value || 1)
。
console.log(100 + (undefined || 1)); // 101
如果您只是想为value
提供默认值1,则可以在签名中进行设置。如果value
未定义,则会为其分配1
的值。并使用功能状态更新。
const handleCounterChange = (action, value = 1) => {
switch (action) {
case "+":
setCounter(counter => counter + value);
break;
case "-":
setCounter(counter => counter - value);
break;
default:
setCounter(counter => counter + value);
break;
}
};
关于这种“减速器”类型模式的补充说明是,如果该操作不是您专门处理的操作,则返回现有状态。
const handleCounterChange = (action, value = 1) => {
switch (action) {
case "+":
setCounter(counter => counter + value);
break;
case "-":
setCounter(counter => counter - value);
break;
default:
// ignore, i.e. don't update state at all
break;
}
};
答案 1 :(得分:2)
这里提出了两个出色的重构。我绝对希望通读建议并进行重构。
对于导致不可预测的计数器的原因,假设单击参数进入了状态更新功能,则存在操作顺序问题。考虑这种情况。
undefined
从编写上述代码的方式来看,当值为undefined
时,我们希望将value
的数字添加到counter
状态。由于操作顺序,这不是正在发生的事情。这个错误很明显,因为value
和counter
经常都是1
,所以状态似乎没有改变。
> let value = undefined
undefined
> let counter = 1
undefined
> counter + value || 100
100
最后一条陈述是“加法计数器加undefined
”,它是NaN
,也是虚假的。在这种情况下,结果将始终是'or'语句100
的另一端。
使用括号可以更改操作顺序,并创建所需的行为。
> counter + (value || 100)
101
答案 2 :(得分:0)
本质上来说,这不是一个答案,但是请不要使用额外的不必要功能使您的代码过于复杂。您的逻辑是如此简单,添加了额外的功能使它的读取变得更加复杂,并添加了奇怪的逻辑(默认设置是什么?)
return (
<div className={classes.Counter}>
<CounterOutput value={counter} />
<CounterControl
label="+"
clicked={() => setCounter(state => state+1)}
/>
<CounterControl
label="-"
clicked={() => setCounter(state => state-1)}
/>
<CounterControl
label="+ 5"
clicked={() => setCounter(state => state+5)}
/>
<CounterControl
label="- 5"
clicked={() => setCounter(state => state-5)}
/>
</div>
);
如果您希望将其干燥多一点,则可以始终执行以下操作:
const change = by => () => setCounter(count => count+by)
return (
<div className={classes.Counter}>
<CounterOutput value={counter} />
<CounterControl
label="+"
clicked={change(1)}
/>
<CounterControl
label="-"
clicked={change(-1)}
/>
<CounterControl
label="+ 5"
clicked={change(5)}
/>
<CounterControl
label="- 5"
clicked={change(-5)}
/>
</div>
);