Dispatch和setState不能一起工作,但它们是独立的

时间:2017-03-28 11:25:28

标签: javascript reactjs redux

我有一个DatePicker组件,当我点击一个新的日期时,它应该在redux商店中设置更改日期,并且还明显地看待UX。

我会将我的代码放在下面,由于handleChange函数中的某些原因,setStatethis.props.addFitler都关闭,redux存储更新正确但是用户体验没有。 但是,如果我注释掉this.props.addFilter调度功能,那么UX更新正确(显然商店没有)。

为什么这两个都不能一起工作?我已经尝试改变它们被调用的顺序,将每个函数提取到另一个函数中,使用mapDispatchToProps而不是直接调用动作创建器,但都无济于事。

DatePicker.js:

import DatePicker from 'react-datepicker';

class DatePick extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      date: moment()
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(date) {
    const { dashboardName } = this.props;
    const { name } = this.props.column;
    this.props.addFilter(date, dashboardName, name);
    this.setState({date});
  }
  render() {
    return (
      <div style={{display: 'inline-block', fontWeight: 'bold'}}>
        <DatePicker
          dateFormat="DD/MM/YYYY"
          selected={this.state.date}
          onChange={this.handleChange} />
      </div>
    );
  }
}

const mapActionToProps = {
  addFilter
};

export default connect(null, mapActionToProps)(DatePick);

handleChange函数中出现的'date'参数是一个时刻对象,就像用于设置initialState的那个一样,所以这不是问题。

附加信息:如果我在setState()之前和之后控制日志,它会同时记录初始状态。

是否有人遇到此问题或有任何想法?如果您需要查看我的redux,我可以使用更多代码更新帖子,但我不认为这是问题,因为它更新了商店。

2 个答案:

答案 0 :(得分:1)

我找到了解决方案,动作创建者调用正在进行一些同步操作,整个UI线程被锁定,直到它完成它所做的任何事情。因此,我们可以在setTimeout的帮助下稍微延迟调用,一切都会按预期进行

答案 1 :(得分:0)

我不认为setTimeout是上一个答案中所建议的很好的解决方案。我们无法确定操作创建者花费的实际时间(因为它可能包含异步调用,例如API调用)。这将再次导致缺少setState渲染的原始问题。再次设置较长的超时将是不好的做法。您的申请将有不必要的延迟。

解决方案

  1. 一种可能的解决方案是使用setState的回调方法来触发动作创建者。

    handleChange(date) {
        const { dashboardName } = this.props;
        const { name } = this.props.column;
        this.setState({date}, () => { 
            this.props.addFilter(date, dashboardName, name); 
        });
    }
    

    在这种情况下,setState渲染完成后将触发动作创建者。

  2. 其他解决方案是在收到新道具时使用反应生命周期方法来运行setState 这样,在动作创建者退回道具并更改状态之后,setState被触发。

    componentWillRecieveProps (nextProps) {
        // check the related prop is changed
        // setState
    }
    

    但是使用react 17时,此方法将很快被弃用。以下是新的稳定替代品。 https://hackernoon.com/problematic-react-lifecycle-methods-are-going-away-in-react-17-4216acc7d58b

    static getDerivedStateFromProps(nextProps, prevState) {
        // check the related prop is changed
        // setState
    }