React useState setter 如何在不使用状态变量的情况下更新此状态变量?

How can a React useState setter update this state variable without using the state variable?

有人可以解释为什么这段代码有效吗?

import { useState } from 'react';

export default function RandomList() {
    const [numbers, setNumbers] = useState([]);

    const addNumber = () => {    
        setNumbers(whatever => {
            return [...whatever, Math.random()];
        });
    };

    return (
        <div>
            <h1>Random Numbers</h1>
            <button onClick={addNumber}>Add a Number</button>
            <ul>
                {numbers.map((number, index) => (
                    <li key={index}>{number}</li>
                ))}
            </ul>
        </div>
    );
}

即:

(1) whatever 存储在哪里,是在函数内部的闭包中吗?或者它只是一个临时参数,用于更新 numbers 的内部状态?

(2) 像上面的代码那样将函数发送到 useState setter 而不是这样做有什么好处:

numbers.push(Math.random());
setNumbers([...numbers]);

Where is whatever being stored,

whatever 是您创建的函数的参数。 React 将调用您的函数,将状态的当前值作为该参数传递,然后您 return 您想要的新状态。

Is there any advantage in sending a function into the useState setter as in the above code, rather than doing this:

set state 的函数版本保证您使用的是状态的最新值,因此它不可能出现与陈旧的闭包变量相关的错误类别。

例如,如果您尝试在不使用该函数的情况下连续两次设置状态,则第二次设置的状态将覆盖第一次,因此您只会得到一个新数字:

setNumbers([...numbers, Math.random()]);
setNumbers([...numbers, Math.random()]);

但是如果您改用函数版本,它将保留两个更改:

setNumbers(prev => [...prev, Math.random()]);
setNumbers(prev => [...prev, Math.random()]);

当然,您可能不会将这样的两行代码紧挨着写,但在复杂的组件中,您可以获得类似的行为,只是代码行没有那么明显的相关性。

Is there any advantage in sending a function into the useState setter as in the above code, rather than doing this:

setNumbers([...numbers]); 更新状态时,更改不会立即反映在计数变量中。相反,React 安排状态更新,并在语句 const [numbers, setNumbers] = useState([]); 的下一次渲染期间,钩子将新状态值分配给数字。

所以为了避免这种异步性质,我们将回调传递给 setNumber();