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

pet*_*gan 3 javascript ecmascript-6 reactjs

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

有关如何调用setState作为回调传递的函数的首选方法.

以下两种方法都有效,但使用其中一种方法有什么影响吗?

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

要么

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

    }
  }, () => this.clearResult(500))
Run Code Online (Sandbox Code Playgroud)

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

  clearResult(time) {

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

  }
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 9

以下两种方法都有效,但使用其中一种方法有什么影响吗?

有一个正确的含义:第一个是不正确的,第二个是正确的.:-)

在你的第一个例子,你调用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
Run Code Online (Sandbox Code Playgroud)

这是证明您的第一个示例在调用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")
);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

() => this.clearResult(500)相反,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")
);
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


旁注1:如果您愿意,您可以更简洁一点:

this.setState(
    () => ({ result: '1-1' }),
    () => this.clearResult(500)
);
Run Code Online (Sandbox Code Playgroud)

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

this.setState(
    { result: '1-1' },
    () => this.clearResult(500)
);
Run Code Online (Sandbox Code Playgroud)

,如果你正在使用从什么是好的this.statethis.props.在这种情况下,使用回调的形式和它的prevStateprops参数.总是.总是使用回调形式没有什么害处,函数调用的开销在现代JavaScript引擎上异常微不足道.(这对本世纪最慢的JS引擎来说甚至是微不足道的:IE6中的那个.)

更多关于这里这里.

  • @peterflanagan:电脑很快.它似乎工作,因为你有500毫秒的超时.如果删除超时,您将看到未按所需顺序调用这些函数. (2认同)