到目前为止,我看到了两种处理切换的方法
首先,根据先前状态设置状态
export default function App() {
const [show, setShow] = useState(false);
const handleClick = () => {
setShow(s => !s);
};
return (
<div>
<div>show: {String(show)}</div>
<button onClick={handleClick}>BTN</button>
</div>
);
}
第二次,直接将状态作为参数传递
export default function App() {
const [show, setShow] = useState(false);
const handleClick = () => {
setShow(!show);
};
return (
<div>
<div>show: {String(show)}</div>
<button onClick={handleClick}>BTN</button>
</div>
);
}
哪个是正确的?据我了解,由于设置状态为异步,第二个可能不起作用,如果我多次单击该按钮,则可能无法获得正确的状态
答案 0 :(得分:4)
第一个是正确的:
setShow(s => !s);
尽管第二个在这种情况下有效,但这是不正确的:
// bad code
setShow(!show);
为什么?
设置状态是异步的-但这的真正含义是将设置状态推迟到重新渲染。
一个例子:
const [myNum, setMyNum] = useState(0)
const handleUpdate = () => {
setMyNum(myNum + 1)
}
如果我们调用handleUpdate
函数,则myNum
的新值将增加1。这可以正常工作,但是呢:
const [myNum, setMyNum] = useState(0)
const handleUpdate = () => {
setMyNum(myNum + 1)
setMyNum(myNum + 1)
}
您可能认为myNum
现在是2,但不是,仍然是1。
之所以会这样,是因为myNum
的值在重新渲染之前不会改变,因此您实际上是在编写:
const handleUpdate = () => {
setMyNum(0 + 1)
setMyNum(0 + 1)
}
因此,如果您依赖于先前的值,您应该始终提供设置状态的功能。
这正常工作:
const handleUpdate = () => {
setMyNum(p => p + 1)
setMyNum(p => p + 1)
}
myNum
现在是2。
即使只设置一次该值,也应保持良好的操作习惯。当您的应用变得复杂并且随时可以通过几种不同的操作设置状态时,您不想被几个月前写的从未想到的事情所吸引。