在 React Hooks 中我们还需要功能性的 setState 方式吗?
Do we still need functional setState way in react hooks?
const [count, setCount] = useState(0);
const handleClick = () =>
setCount(prevCount => {
return prevCount + 1;
});
const [count, setCount] = useState(0);
const handleClick = () => setCount(count + 1);
来自class组件化背景,使用函数式setState
成为一种习惯。我想知道我们是否还需要在函数挂钩中依赖 prevState?或者当前状态总是 "trustable" 而大多数 "updated"?
是,行为相似。
React 正在批处理更新调用。
写作时:
const handleClick = () => setCount(count + 1)
handleClick()
handleClick()
handleClick()
状态中的 count
将为 1
写作时:
const handleClick = () =>
setCount(prevCount => {
return prevCount + 1;
});
handleClick()
handleClick()
handleClick()
状态中的 count
将为 3
State updater function 在 class 和功能组件中都是必需的。 this.setState
不应该和this.state
一起使用,同样适用于useState
状态和setter状态。 useState
不使用状态更新器会导致错误行为的情况更多。
在 class 组件中,使用 this.state
的唯一问题是由于异步状态更新导致的竞争条件:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 }); // overwrites with stale count
console.log(this.state.count); // not updated
}
当没有竞争条件时,this.state
可以在组件内的任何地方访问,因为 this
引用保持不变:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
setTimeout(() => {
this.setState({ count: this.state.count + 1 });
}, 100)
setTimeout(() => {
console.log(this.state.count);
}, 200)
}
在功能组件中,使用useState
状态的问题是功能范围。没有这样的对象可以通过引用访问,状态是通过值访问的,在重新渲染组件之前不会更新:
const [count, setCount] = useState(0);
useEffect(() => {
// runs once on mount
// count is always 0 in this function scope
setCount({ count: count + 1 });
setTimeout(() => {
setCount({ count: count + 1 }); // overwrites with stale count
}, 100)
setTimeout(() => {
console.log(count); // not updated
}, 200)
}, []);
const [count, setCount] = useState(0);
const handleClick = () =>
setCount(prevCount => {
return prevCount + 1;
});
const [count, setCount] = useState(0);
const handleClick = () => setCount(count + 1);
来自class组件化背景,使用函数式setState
成为一种习惯。我想知道我们是否还需要在函数挂钩中依赖 prevState?或者当前状态总是 "trustable" 而大多数 "updated"?
是,行为相似。
React 正在批处理更新调用。 写作时:
const handleClick = () => setCount(count + 1)
handleClick()
handleClick()
handleClick()
状态中的 count
将为 1
写作时:
const handleClick = () =>
setCount(prevCount => {
return prevCount + 1;
});
handleClick()
handleClick()
handleClick()
状态中的 count
将为 3
State updater function 在 class 和功能组件中都是必需的。 this.setState
不应该和this.state
一起使用,同样适用于useState
状态和setter状态。 useState
不使用状态更新器会导致错误行为的情况更多。
在 class 组件中,使用 this.state
的唯一问题是由于异步状态更新导致的竞争条件:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 }); // overwrites with stale count
console.log(this.state.count); // not updated
}
当没有竞争条件时,this.state
可以在组件内的任何地方访问,因为 this
引用保持不变:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
setTimeout(() => {
this.setState({ count: this.state.count + 1 });
}, 100)
setTimeout(() => {
console.log(this.state.count);
}, 200)
}
在功能组件中,使用useState
状态的问题是功能范围。没有这样的对象可以通过引用访问,状态是通过值访问的,在重新渲染组件之前不会更新:
const [count, setCount] = useState(0);
useEffect(() => {
// runs once on mount
// count is always 0 in this function scope
setCount({ count: count + 1 });
setTimeout(() => {
setCount({ count: count + 1 }); // overwrites with stale count
}, 100)
setTimeout(() => {
console.log(count); // not updated
}, 200)
}, []);