我们还需要在 React 钩子中使用函数式 setState 方式吗?

IT技术 javascript reactjs react-native react-hooks
2021-04-19 09:58:10
  const [count, setCount] = useState(0);

  const handleClick = () =>
    setCount(prevCount => {
      return prevCount + 1;
    });
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(count + 1);

来自基于类的组件背景,它成为我们使用功能性的习惯setState我想知道我们是否还需要在功能钩子中依赖 prevState ?或者当前状态始终是“可信赖的”和最“更新的”?

2个回答

是的,行为是相似的。

React 正在批处理更新调用。写作时:

const handleClick = () => setCount(count + 1)
handleClick()
handleClick()
handleClick()

count状态将是1

写作时:

const handleClick = () =>
  setCount(prevCount => {
    return prevCount + 1;
});
handleClick()
handleClick()
handleClick()

count状态将是3

谢谢,这个例子非常清楚这是如何工作的。这解释了为什么我的组件中的切换功能在尝试逻辑上不是存储在 state 中的布尔值时无法正常工作。
2021-06-05 09:58:10

状态更新器功能在类和功能组件中都是必需的。this.setState不应与 一起使用this.state,这同样适用于useState状态和状态设置器。还有更多的情况useState时,不使用状态更新将导致错误的行为。

在类组件中,使用 的唯一问题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)
}, []);