繁体   English   中英

在父组件中执行异步调用后,使用props更新,更新子组件中的状态

[英]React, updating state in child component using props after async call in parent component

我正在构建一个天气应用程序,我正在寻找一些建议,以便根据父组件从父组件发出异步调用后从父组件发送的道具更新子组件中的状态。

我有一个父组件,它在componentDidMount()方法中对navigator.geolocation进行异步/ await调用,并返回我想要作为props发送给子组件的纬度和经度。 然后,在子组件中,我需要使用来自props的lat和long对OpenWeatherMap API进行异步/等待调用。 然后我需要使用response setState() 我不能在子节点中使用componentDidMount() ,因为它在父async / await调用返回之前安装。

问题是应用程序流:父组件安装和渲染,向子项发送道具为null 子组件使用null道具进行安装和渲染。 然后,async / await在parent中返回响应,在componentDidMount()中将响应设置为latlong ,parent重新呈现并向具有正确值的子项发送props作为latlong 子组件使用props中的正确值更新。 现在,此时我需要使用那些道具来设置setState() ,但是我显然无法在componentDidUpdate()执行它而不重新渲染到无限循环中。

那么,完成这项任务的好方法是什么?

父母组成部分:

class Container extends React.Component {
  state = {
    cityState: {
      city: "",
      state: ""
    },
    latLong: {
      lat: null,
      long: null
    }
  };

  componentDidMount() {
    this.getCityAndState();
  }

  getCityAndState() {
    let latlng = "";
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(async position => {
        latlng = `${position.coords.latitude},${position.coords.longitude}`;

        const response = await googleGeolocation.get(
          `json?latlng=${latlng}&location_type=APPROXIMATE&result_type=locality&key=${APIkey}`
        );

        this.setState({
          cityState: {
            city: response.data.results[0].address_components[0].long_name,
            state: response.data.results[0].address_components[2].short_name
          },
          latLong: {
            lat: position.coords.latitude,
            long: position.coords.longitude
          }
        });
      });
    }
  }

  render() {
    return (
      <div className="container">
        <LocationTime location={this.state.cityState} />
        <Forecast location={this.state.latLong} />
      </div>
    );
  }
}

儿童成分:

class Forecast extends React.Component {
  state = {
    today: {},
    secondDay: {},
    thirdDay: {},
    fourthDay: {},
    fifthDay: {}
  };

  async componentDidUpdate() {
    ********** A bunch of logic in here to extract Weather API response 
into 5 separate arrays which will each be sent to the <Day /> child components
after setting the state to those arrays(which doesn't work in this 
life-cycle method, currently) **********

  }

  render() {
    return (
      <div className="forecast">
        <Day forecast={this.state.today} />
        <Day forecast={this.state.secondDay} />
        <Day forecast={this.state.thirdDay} />
        <Day forecast={this.state.fourthDay} />
        <Day forecast={this.state.fifthDay} />
      </div>
    );
  }
}

PS我总是问复杂的问题,以相当简单的答案结束,哈哈

您可以使用componentWillReceiveProps生命周期方法。

第一个子组件呈现一些道具,如latlng为null,那么你可以做类似的事情:

async componentWillReceiveProps(nextProps) {
  if ( this.props.lat !== nextProps.lat || this.props.lng !== nextProps.lng ) {
    const response = await YourAPICall(nextProps.lat, nextProps.lng)
    this.setState(/* set your things here */)
  }
}

显然这只是一个大纲......

不确定为什么使用async / await而不是普通的fetch / axios调用。 为了防止在你提到的componentDidUpdate进入无限循环,你需要运行一个条件语句,如:

componentDidUpdate(prevState){
 if (this.props.propertyYouWantToCheck !== prevState.propertyYouWantToCheck){
   // set your state/logic here
 }
}

您还可以考虑仅在父组件中使用获取数据,并将其传递给子组件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM