react set state回调正确的方式传递参数

时间:2018-02-07 15:12:34

标签: javascript reactjs ecmascript-6

我正在使用React的setState方法,并在状态更新后调用另一个函数。

是否有一种首选方法可以调用作为回调传递给setState的函数。

以下两种方法都有效,但使用其中一种方法会产生什么性能影响?

  this.setState(prevState => {
    return {
      result: '1-0'
    }
  }, this.clearResult(500))

  this.setState(prevState => {
    return {
      result: '1-1',

    }
  }, () => this.clearResult(500))

我的clearPin方法如下所示。所有这些代码都在React组件中。

  clearResult(time) {

    setTimeout(() => {
      this.setState({
        result: '0-0'
      })
    }, time)

  }

1 个答案:

答案 0 :(得分:8)

  

以下两种方法都有效,但使用其中一种方法会产生什么性能影响?

有一个正确性暗示:第一个是不正确的,第二个是正确的。 : - )

在您的第一个示例中,您呼叫this.clearResult(500)然后呼叫setState(调用this.clearResult(500) - undefined的结果,在你的例子中 - 作为它的第二个参数)。 this.setState(prevState => { ... }, this.clearResult(500));foo(bar())类似 - 首先调用bar,然后将调用结果传递给foo

在第二个示例中,您将函数传递给setState,它将在状态更新时调用。

你想要第二种形式(或其中的一种形式)。

this.setState(prevState => {
  return {
    result: '1-1',
  }
}, () => this.clearResult(500));
// or:  }, this.clearResult.bind(this, 500));
// But the arrow is clear and idiomatic

以下是您的第一个示例在调用clearResult之前调用setState 之前以及调用状态更改回调之前的证据:

class Example extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {value: "a"};
  }
  
  // Overriding it PURELY to show what's happening
  setState(...args) {
    console.log("setState called");
    return super.setState(...args);
  }
  
  componentDidMount() {
    this.setState(
      () => {
        console.log("state change callback");
        return {value: "b"};
      },
      this.clearResult(500)
    );
  }
  
  clearResult(delay) {
    console.log("clearResult called");
    setTimeout(() => {
      this.setState({value: "c"});
    }, delay);
  }
  
  render() {
    return <div>{this.state.value}</div>;
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

而使用() => this.clearResult(500)代替clearResultsetState之后(以及状态更改后):

class Example extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {value: "a"};
  }
  
  // Overriding it PURELY to show what's happening
  setState(...args) {
    console.log("setState called");
    return super.setState(...args);
  }
  
  componentDidMount() {
    this.setState(
      () => {
        console.log("state change callback");
        return {value: "b"};
      },
      () => this.clearResult(500)
    );
  }
  
  clearResult(delay) {
    console.log("clearResult called");
    setTimeout(() => {
      this.setState({value: "c"});
    }, delay);
  }
  
  render() {
    return <div>{this.state.value}</div>;
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

附注1:如果你愿意,你可以更简洁一点:

this.setState(
    () => ({ result: '1-1' }),
    () => this.clearResult(500)
);

附注2:如果您根据当前状态或道具传递的新状态不是,则无需使用函数表单。在你的例子中,它不是,所以你的是使用非回调表单的地方之一是好的:

this.setState(
    { result: '1-1' },
    () => this.clearResult(500)
);

如果您使用this.statethis.props中的内容,那么就不会。在这种情况下,请使用回调表单及其prevStateprops参数。总是。总是使用回调形式没有什么害处,函数调用的开销在现代JavaScript引擎上异常微不足道。 (这对本世纪最慢的JS引擎来说甚至是微不足道的:IE6中的那个。)

有关herehere的更多信息。