setState()不能实时设置

时间:2019-01-14 06:26:15

标签: reactjs

嗨,我在通过props设置组件状态值时遇到麻烦:

    this.state = {
      date: '',
      dailiesInformation: [],
      isDailiesInformation: false
    };
  }

  componentWillReceiveProps(props) {
    this.setState({ date: props.dateValue }, this.updateCards);
  }

  updateCards = async() => {
    const currentDate = moment(this.state.date).format('YYYY-MM-DD');
    let dailies = await api.get(`/daily/${currentDate}`);
    this.setState({ dailiesInformation: dailies.data.allDailies });
  }

我想通过updateCards函数设置dailiesInformation属性,但是它比当前设置落后1步,我将此函数作为回调传递给componentWillReceiveProps()函数,但是它不起作用。

我做错了什么?谢谢你的帮助。

3 个答案:

答案 0 :(得分:1)

我认为您的 SetState 需要更改

componentWillReceiveProps(nextProps) {
    this.setState({ date: nextProps.dateValue, dailiesInformation: this.updateCards});
}

但是componentWillReceiveProps是不安全的生命周期挂钩,而不是异步调用的正确位置,请检查https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops

请勿为此使用componentWillReceiveProps,而应在使用构造函数时直接使用道具。

 Constructor(props){
  super();
  this.state = {
      date: props.dateValue,
      dailiesInformation: this.updateCards,
      isDailiesInformation: false
    };
  }

  updateCards = async() => {
    const currentDate = moment(this.state.date).format('YYYY-MM-DD');
    let dailies = await api.get(`/daily/${currentDate}`);
    return dailies.data.allDailies;
  }

答案 1 :(得分:1)

我会建议这样的模式(理想情况下,容器是一些全局状态管理容器)。每当App(而非dailiesInformation)的任何道具发生变化时,应用程序都会通过getDailies发送新请求,并通过dailiesInformation道具获取结果。 考虑不建议使用componentWillReceiveProps,建议改用静态getDerivedStateFromProps

class App extends React.Component {
  static getDerivedStateFromProps(props, state){
    const { dailiesInformation, ...otherProps } = props;

   const { dailiesInformation: prevDailyInfo, ...prevOtherProps } = state.prevProps;
    
   const isNewOtherProps = JSON.stringify(otherProps) !== JSON.stringify(prevOtherProps);
       
    if (isNewOtherProps) {
      props.getDailies();
    }
      
    return { prevProps: props }
  }
  
  
  state = {
    prevProps: { dailiesInformation: null },
  }

  render() {
    const { dailiesInformation } = this.props;
    return `dailiesInformation: ${dailiesInformation}`;
  }
}

//-------------------

class Container extends React.Component {
  handleGetDailies = () => setTimeout(() => this.setState({dailiesInformation: Math.random()}), 500);
  
  state = { dailiesInformation: 0, someProp: null }
  
  changeSomeProp = () => {
    this.setState({ someProp: Math.random() })
  }
  
  render() {
    const { dailiesInformation, someProp } = this.state;

    return (
     <div>
       <button onClick={this.changeSomeProp}>Change prop</button><br /><br />
       <App
        someProp={someProp}
        getDailies={this.handleGetDailies}
        dailiesInformation={dailiesInformation}
       />
     </div>
    )
  }
}



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

答案 2 :(得分:0)

您最好尝试以下链接中说明的做法。 建议使用这种方式来接收新道具和更新状态,并同时处理异步操作:

https://gist.github.com/bvaughn/982ab689a41097237f6e9860db7ca8d6

componentWillReceiveProps不是调用延迟/异步方法的正确位置。