何时使用 useState() 挂钩的功能更新形式,例如。 setX(x=>x+1)
When to use functional update form of useState() hook, eg. setX(x=>x+1)
通常当我们需要更新功能组件中的状态时,我们会这样做:
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>);
}
我们何时以及为何需要使用功能更新表单?
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>You clicked {count} times</p>
<button onClick={() => setCount(c=>c + 1)}>
Click me
</button>
</div>);
}
当 setter 可能关闭旧状态值时使用函数形式。
例如,如果启动异步请求,并且您想在完成后更新状态,则发出的请求将具有请求开始时的状态范围,这可能不是与最新的渲染状态相同。
如果刚刚更新了相同的状态值,您可能还需要使用函数形式,例如
setValue(value + 1);
// complicated logic here
if (someCondition) {
setValue(value => value + 1);
}
因为 setValue
的第二次调用结束了旧的 value
。
状态更新可能是异步的:
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
useState
在这种情况下与setState相同。
两次调用set state时可以看到不同:
<button
onClick={() => {
setCount(count + 1);
setCount(count + 1);
}}
></button>;
<button
onClick={() => {
setCount(c => (c + 1));
setCount(c => (c + 1));
}}
></button>;
据此:https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
当可能调用多个 setState 挂钩(异步)时(例如,如果用户垃圾邮件点击按钮)
而且由于其异步性质,状态不会在函数内立即更新,例如:
func() {
console.log(counter) // counter = 1
setCounter(counter => counter + 1) // counter = 1
console.log(counter) // counter = 1
}
还有其他用例。例如,当您在效果中调用 useState
时。如果新状态依赖于旧状态,这可能会导致无限循环。
useEffect(() => {
setCounter(counter + 1);
}, [counter]);
您可以通过使用功能更新来避免这种情况:
useEffect(() => {
setCounter(old => old + 1);
}, []);
功能更新形式还允许将更新功能传递给其子级,同时仍然可以访问父级的状态。
function MyButton(props){
// return <button onClick={()=>props.onClick(count+1)}>+1</button>; // error as count is not exposed here
return <button onClick={()=>props.onClick(n=>(n+1))}>+1</button>;
}
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>Counter: {count}</p>
<MyButton onClick={setCount}/>
</div>);
}
ReactDOM.render(<Example/>,document.querySelector("div"));
通常当我们需要更新功能组件中的状态时,我们会这样做:
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>);
}
我们何时以及为何需要使用功能更新表单?
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>You clicked {count} times</p>
<button onClick={() => setCount(c=>c + 1)}>
Click me
</button>
</div>);
}
当 setter 可能关闭旧状态值时使用函数形式。
例如,如果启动异步请求,并且您想在完成后更新状态,则发出的请求将具有请求开始时的状态范围,这可能不是与最新的渲染状态相同。
如果刚刚更新了相同的状态值,您可能还需要使用函数形式,例如
setValue(value + 1);
// complicated logic here
if (someCondition) {
setValue(value => value + 1);
}
因为 setValue
的第二次调用结束了旧的 value
。
状态更新可能是异步的:
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
useState
在这种情况下与setState相同。
两次调用set state时可以看到不同:
<button
onClick={() => {
setCount(count + 1);
setCount(count + 1);
}}
></button>;
<button
onClick={() => {
setCount(c => (c + 1));
setCount(c => (c + 1));
}}
></button>;
据此:https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
当可能调用多个 setState 挂钩(异步)时(例如,如果用户垃圾邮件点击按钮)
而且由于其异步性质,状态不会在函数内立即更新,例如:
func() {
console.log(counter) // counter = 1
setCounter(counter => counter + 1) // counter = 1
console.log(counter) // counter = 1
}
还有其他用例。例如,当您在效果中调用 useState
时。如果新状态依赖于旧状态,这可能会导致无限循环。
useEffect(() => {
setCounter(counter + 1);
}, [counter]);
您可以通过使用功能更新来避免这种情况:
useEffect(() => {
setCounter(old => old + 1);
}, []);
功能更新形式还允许将更新功能传递给其子级,同时仍然可以访问父级的状态。
function MyButton(props){
// return <button onClick={()=>props.onClick(count+1)}>+1</button>; // error as count is not exposed here
return <button onClick={()=>props.onClick(n=>(n+1))}>+1</button>;
}
function Example() {
const [count, setCount] = React.useState(0);
return (<div><p>Counter: {count}</p>
<MyButton onClick={setCount}/>
</div>);
}
ReactDOM.render(<Example/>,document.querySelector("div"));