在 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)
}, []);