Реакция обновления состояния в дочернем компоненте с использованием реквизита после асинхронного вызова в родительском компоненте - PullRequest
0 голосов
/ 03 февраля 2019

Я создаю приложение погоды и ищу несколько советов для получения рекомендаций по обновлению состояния в дочернем компоненте на основе реквизитов, отправленных из родительского компонента ПОСЛЕ асинхронного вызова из родительского компонента.

У меня есть родительский компонент, который выполняет асинхронный / ожидающий вызов в методе componentDidMount() для navigator.geolocation и возвращает широту и долготу, которые я хочу отправить дочернему компоненту в качестве реквизита.Затем в дочернем компоненте мне нужно сделать async / await вызов API OpenWeatherMap, используя lat и long из реквизита.Затем мне нужно setState(), используя response.Я не могу использовать componentDidMount() в дочернем процессоре, потому что он монтируется до того, как родительский вызов async / await возвращается.

Проблема заключается в потоке приложения: родительский компонент монтируется и обрабатывается, отправляя реквизиты дочернему элементу как * 1010.*.Дочерний компонент монтируется и обрабатывается с помощью null реквизита.Затем async / await возвращает ответ в parent, устанавливает lat и long из ответа на состояние в componentDidMount(), родительский объект повторно отображает и отправляет реквизиты для потомков с правильными значениями, такими как 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>
    );
  }
}

ДЕТСКИЙ КОМПОНЕНТ:

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 Я всегда задаю запутанные вопросы, которые заканчиваются довольно простыми ответами, lol

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Не уверен, почему вы используете async / await вместо обычного вызова fetch / axios.Чтобы не допустить вхождения в бесконечный цикл в вашем componentDidUpdate, как вы упомянули, вам нужно запустить условный оператор, например:

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

Также вы можете рассмотреть возможность использования выборочных данных только вродительский компонент и передать его дочернему компоненту.

0 голосов
/ 03 февраля 2019

Вы можете использовать метод жизненного цикла componentWillReceiveProps.

Первый дочерний компонент отображает некоторые реквизиты, такие как lat и lng, равные 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 */)
  }
}

Очевидно, это всего лишь набросок ...

...