反应这在setState的回调中有时不起作用

时间:2018-04-18 01:54:03

标签: javascript reactjs setstate

假设

callback = () => { ... }

我应该何时使用

this.setState({...}, this.callback);

我应该何时使用

this.setState({...}, () => { this.callback(); });

确保this.callback方法中仍然有效。

我们应该遵循一些基本规则吗?

2 个答案:

答案 0 :(得分:1)

两者都是等效的,取决于你如何设置其余的课程。

如果您希望thiscallback方法中有效,则有2个选项:

I)在构造函数中绑定回调:

class YourComp extends React.Component {
  constructor(props) {
    super(props);
    this.callback.bind(this);
  }

  callback() { ... }
}

II)将你的回调声明为lambda(我通常更喜欢这种方法,因为没有忘记绑定它的风险)

class YourComp extends React.Component {
  callback = () => { ... your code ... }
}

答案 1 :(得分:0)

为什么在一开始我问这个问题是我遇到过这样的场景

componentWillReceiveProps(nextProps) {
    const { envId, serviceName } = this.props;
    if (envId !== nextProps.envId || serviceName !== nextProps.serviceName) {
      this.reloadService();
    }
  }

reloadService = () => {
    const { envId, serviceName, dispatch } = this.props; // version - 1
    this.setState({ loading: true }, () => {
      const { envId, serviceName, dispatch } = this.props; // version -2
      dispatch(ProdcutActions.fetchServiceDetail(envId, serviceName))
            .then(response => response.data)
            .then((serviceVo) => {
              this.setState({ serviceVo, loading: false });
            });
    });
  }

正如您所看到的,reloadService更新时使用parameters。最初,我使用了版本 - 1 ,因为我计划稍后使用这些值,并且作为 follow-rule保守的程序员,我打算声明要成为的 - 在方法的最开始使用变量然后我陷入这个混乱 - 阴险的错误。

正如预期的那样,我总是遇到一个状态后面的情况,因为声明的变量会更新,但由于闭包机制,回调将引用旧的过时的变量。但是,如果我们直接提取 回调成员方法,它将正常工作。

componentWillReceiveProps(nextProps) {
    const { envId, serviceName } = this.props;
    if (envId !== nextProps.envId || serviceName !== nextProps.serviceName) {
      this.reloadService();
    }
}

reloadService = () => {
    this.setState({ loading: true }, this.updateServiceDo);
}
updateServiceDo = () => {
    const { envId, serviceName, dispatch } = this.props;
    dispatch(ProdcutActions.fetchServiceDetail(envId, serviceName))
          .then(response => response.data)
          .then((serviceVo) => {
            this.setState({ serviceVo, loading: false });
          });
}

或者你可以选择版本 - 2 ,如果你不像我一样保守。