在父组件中进行异步调用后,使用prop进行反应,更新子组件中的状态

时间:2019-02-02 23:18:45

标签: javascript reactjs async-await state

我正在构建一个天气应用程序,我正在寻找一些最佳做法的建议,这些建议是在父组件异步调用之后基于父组件发送的道具更新子组件状态的。

我有一个父组件,该父组件在componentDidMount()方法中向navigator.geolocation进行异步/等待调用,并返回纬度和经度,我希望这些纬度和经度作为道具发送给子组件。然后,在子组件中,我需要使用道具的经纬度和经度对OpenWeatherMap API进行异步/等待调用。然后,我需要使用setState() response。我无法在子级中使用componentDidMount(),因为它会在父级异步/等待调用返回之前挂载。

问题在于应用程序流程:父组件安装并渲染,并将道具作为null发送给子组件。子组件将使用null道具进行安装和渲染。然后,异步/等待返回父级的响应,将响应中的latlong设置为componentDidMount()中的状态,父级重新渲染并将道具以正确的值发送给孩子,如{ {1}}和lat。子组件会更新道具中的正确值。现在,我需要使用这些道具long,但是如果不重新渲染为无限循环,显然我不能在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>
    );
  }
}

P.S。我总是问一些复杂的问题,这些问题的答案很简单,大声笑

2 个答案:

答案 0 :(得分:3)

您可以使用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 */)
  }
}

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

答案 1 :(得分:0)

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

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

另外,您可能要考虑仅在父组件中使用获取数据,然后将其传递给子组件。