Состояние не обновляется с помощью setState в функции геолокации - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь обновить состояние, когда получаю координаты из API геолокации. Но состояние не обновляется. Я поместил обратный вызов внутри setState, чтобы проверить, что он получает, чтобы обновить координаты, и он не определен. Но я не могу понять, куда мне поместить этот setState для обновления фактических координат.


class App extends React.Component {
  constructor(props) {
    super(props);
    // App State
    this.state = {
      lat: 0,
      lng: 0
    };
  }
  // ComponentDIDMount
  componentDidMount() {
    // Get Data from json file

    $.getJSON("../resturants.json", data => {
      this.setState({
        resturantsList: data
      });
    });

    // Get location of user
    let success = position => {
      const latitude = position.coords.latitude;
      const longitude = position.coords.longitude;
      console.log(latitude, longitude);
      this.setState(
        {
          lat: latitude,
          lng: longitude
        },
        () => console.log(latitude, longitude)
      );
      console.log(this.state);
    };

    function error() {
      console.log("Unable to retrieve your location");
    }
    navigator.geolocation.getCurrentPosition(success, error);

    // Api call for resturants data
    const proxyurl = "https://cors-anywhere.herokuapp.com/";
    const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${this.state.lat},${this.state.lng}&radius=3000&type=restaurant&key=apikey`;
    console.log(url);
    fetch(proxyurl + url)
      .then(res => res.json())
      .then(
        result => {
          console.log(result.results);
          let apiResturants = result.results;
          let allResturants = this.state.resturantsList.concat(
            ...apiResturants
          );
          this.setState({
            resturantsList: allResturants
          });
        },

        error => {
          console.log("error");
        }
      );
  }
  }

  // Render function for app component
  render() {


  }
}

Ответы [ 3 ]

2 голосов
/ 13 февраля 2020

ЗДЕСЬ РЕШЕНИЕ:

const getData = () => {
// Api call for resturants data
    const proxyurl = "https://cors-anywhere.herokuapp.com/";
    const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${this.state.lat},${this.state.lng}&radius=3000&type=restaurant&key=apikey`;
    console.log(url);
    fetch(proxyurl + url)
      .then(res => res.json())
      .then(
        result => {
          console.log(result.results);
          let apiResturants = result.results;
          let allResturants = this.state.resturantsList.concat(
            ...apiResturants
          );
          this.setState({
            resturantsList: allResturants
          });
        },

        error => {
          console.log("error");
        }
      );
  }
}


componentDidMount(){

  const success = position => {
  this.setState({lat: position.latitude, long: position.longitude}, () => {
  this.getData();
  })
  }
}

setState - асинхронная c операция, которая означает, что обновление состояния будет завершено в будущем. Если вы хотите проверить, когда обновляется состояние, вы можете использовать второй аргумент.

this.setState({lat:latitude, long: longitude}, () => {console.log(this.state)});

Этот второй обратный вызов сообщит вам точную проблему, поскольку он будет вызван после завершения обновления состояния.

1 голос
/ 13 февраля 2020

Не выполнять асинхронные вызовы и не вызывать this.setState в конструкторе реагирующих компонентов .

Вы не должны вызывать setState () в конструкторе ().

Используйте функцию жизненного цикла componentDidMount для извлечения данных и обновления состояния.

constructor(props) {
  super(props);

  // App State
  this.state = {
    lat: 0,
    lng: 0
  }
};

componentDidMount() {
  // Get location of user
  const success = position => {
    const latitude = position.coords.latitude;
    const longitude = position.coords.longitude;
    console.log(latitude, longitude);
    this.setState({
      lat: latitude,
      lng: longitude
    });
  };

  const error = () => {
    console.log("Unable to retrieve your location");
  };

  navigator.geolocation.getCurrentPosition(success, error);
}

Обновление состояния асинхронное

Обновления состояния реакции являются асинхронными и помещаются в очередь для обработки в конце текущего цикла рендеринга. Вы получаете доступ к значениям состояния из цикла визуализации current , а не для следующего цикла. Переместите значения lat и long, сохраненные из вызова navigator.geolocation.getCurrentPosition, в область действия функции componentDidMount и используйте их в более позднем fetch вместо использования состояния lat & lng.

componentDidMount() {
  // Get Data from json file

  $.getJSON("../resturants.json", data => {
    this.setState({
      resturantsList: data
    });
  });

  // Get location of user
  // Move latitude and longitude to function scope
  let latitude = 0;
  let longitude = 0;

  let success = position => {
    // cache values
    latitude = position.coords.latitude;
    longitude = position.coords.longitude;
    console.log(latitude, longitude);
    this.setState(
      {
        lat: latitude,
        lng: longitude
      },
      () => console.log(latitude, longitude)
    );
    console.log(this.state);
  };

  function error() {
    console.log("Unable to retrieve your location");
  }
  navigator.geolocation.getCurrentPosition(success, error);

  // Api call for resturants data
  const proxyurl = "https://cors-anywhere.herokuapp.com/";
  // use cached lat & long values
  const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${
    latitude
  },${longitude}&radius=3000&type=restaurant&key=apikey`;
  console.log(url);
  fetch(proxyurl + url)
    .then(res => res.json())
    .then(
      result => {
        console.log(result.results);
        let apiResturants = result.results;
        let allResturants = this.state.resturantsList.concat(
          ...apiResturants
        );
        this.setState({
          resturantsList: allResturants
        });
      },

      error => {
        console.log("error");
      }
    );
}
0 голосов
/ 13 февраля 2020

Поскольку вы находитесь в функции жирной стрелки, вы можете переопределить ее с помощью let self = this, а затем использовать self.setState вместо

...