在内部,React 为给定的组件实例保存了一个包含所有状态的数组。例如,如果您有
const comp = () => {
const [state, setState] = useState(0);
const clickHandler = () => setState(prevState => prevState +1);
return <button onClick={clickHandler}>click</button>
};
然后,因为组件只有一种状态,所以在挂载时,React 将有一个包含一个项目的数组,它会在内部存储:
[0]
当useState 被调用时,React 当前在其内部数组中的该状态的值被返回。因此,对于上面的示例,当您单击时,状态设置器将告诉 React 将其内部状态更新为:
[1]
之后组件由于状态变化而重新渲染,所以重新渲染的useState返回的状态值为1。
当您使用状态设置器的回调形式时,例如
setState(prevState => prevState +1);
回调的参数直接来自 React 的内部。有时这比依赖外部状态标识符中的值更可靠,因为如果您之前设置相同的状态而不等待重新渲染,外部状态值将过期 - 例如,请注意以下如何递增每次点击只增加 1 次,而不是 2 次。
const App = () => {
const [count, setCount] = React.useState(0);
const clickHandler = () => {
setCount(count + 1);
setCount(count + 1);
};
return (
<div>
{count}
<button onClick={clickHandler}>click</button>
</div>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>
相反,如果你使用回调版本,一旦你调用第一个 state setter,React 的 state 内部就会更新 - 然后你第二次调用 state setter,传递的参数将是新更新的值 React有它的状态:
const App = () => {
const [count, setCount] = React.useState(0);
const clickHandler = () => {
setCount(count => count + 1);
setCount(count => count + 1);
};
return (
<div>
{count}
<button onClick={clickHandler}>click</button>
</div>
);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>
仅当您有可能关闭过时的关闭时才需要回调方法。如果 state 中的值没有过时的机会,则不需要回调,只需执行
setCount(count + 1);
会正常工作。