示例代码及原因

下面classhooks的写法里,setTimeout 取到的都是旧值,是因为 react 中一直遵循一个原则,即 state 指向的内容是不可变的,所以每一次 state 的更新都是指向变了。注意,这里是state指向变了,并不是释放,只有原来指向的对象没有其它引用的时候,才会被释放

因为闭包的原因,setTimeout中依然指向的原来的对象,所以旧的state没有释放,所以会取到旧值。

react中,组件的每一次 渲染都是那一瞬间的状态

import React, { useState } from "react";
// hooks 示例
function Example2() {
  const [count, setCount] = useState(0);
  function handleAlertClick() {
    setTimeout(() => {
      alert("You clicked on: " + count);
    }, 3000);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <button onClick={handleAlertClick}>Show alert</button>
    </div>
  );
}

// class 示例
class Example extends React.Component {
  state = {
    count: 0
  };
  setCount = count => {
    this.setState(count);
  };
  handleAlertClick = () => {
    setTimeout(() => {
      alert("You clicked on: " + this.state.count);
    }, 3000);
  };
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setCount(this.state.count + 1)}>
          Click me
        </button>
        <button onClick={this.handleAlertClick}>Show alert</button>
      </div>
    );
  }
}

export default Example;

解决办法

使用 ref

function Example() {
  const [count, setCount] = useState(0);
  let ref = useRef();
  ref.current = count;
  function handleAlertClick() {
    setTimeout(() => {
      alert("You clicked on: " + ref.current);
    }, 3000);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <button onClick={handleAlertClick}>Show alert</button>
    </div>
  );
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐