状态未在地理定位功能中使用 setState 进行更新

Posted

技术标签:

【中文标题】状态未在地理定位功能中使用 setState 进行更新【英文标题】:State is not updating using setState in geolocation function 【发布时间】:2020-02-13 05:51:03 【问题描述】:

当我从地理位置 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() 


  

【问题讨论】:

您不得使用this.state=...初始化状态 并且状态更新是异步的,请查看官方文档 你能告诉我这个异步更新是如何影响状态更新的吗? 查看reactjs.org/docs/… 好吧,如果您的日志未定义,那么显然这里的问题不是 React 或 setState,而是您的 API 没有返回您认为返回的内容。登录position 看看它是否提供了什么。如果没有,您需要查看您的 navigator.geolocation.getCurrentPosition 以查看您是否正确使用它。 【参考方案1】:

这是解决方案:

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 是异步操作,表示状态更新将在以后完成。如果要检查状态何时更新,可以使用第二个参数。

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

第二个回调会告诉你确切的问题,因为一旦状态更新完成就会调用它。

【讨论】:

好的,现在我看到回调也返回了准确的位置,但是我如何让 setState 在他获得准确的值时进行状态更新。即纬度/经度 如果您在控制台中记录回调中的状态并获得正确的结果,这意味着状态已更新。 你是绝对正确的,但我有一个 api 调用,它从状态中获取位置变量。即使在状态更新后它也不会发出请求,这让我认为状态没有更新。 const url = https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=$this.state.lat,$this.state.lng&radius=3000&type=restaurant&key=apikey 您正在为 url 使用状态数据,但这不会自动触发请求。状态更新只会触发重新渲染。您必须在 componentDidMount 或其他地方进行请求调用。或者,如果我遗漏了什么,您可以再解释一下。【参考方案2】:

不要进行异步调用,也不要在 React 组件的 constructor 内调用 this.setState

不应该在constructor()中调用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);

状态更新是异步的

React 状态更新是异步的,并在当前渲染周期结束时排队等待处理。您正在访问 当前 渲染周期的状态值,而不是下一个周期的状态值。将 navigator.geolocation.getCurrentPosition 调用保存的 lat 和 long 值移动到 componentDidMount 的函数范围中,并在后面的 fetch 中使用它们,而不是使用状态 latlng

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");
      
    );

【讨论】:

谢谢哥们,ComponentDidMount 就在那里。我只是一开始没有包括它。我的错。 @Mehmood 更新了答案,解释了为什么以后不能在同一个函数中访问状态更新,并提供了一个可能的解决方案。 您好,谢谢。我有我的答案。查看@oneJeet 答案。 @user1864070 谢谢。是的,我不认为链接setState 回调以进行进一步 状态更新是一个好的模式,这就是组件生命周期函数的用途。【参考方案3】:

由于你在一个胖箭头函数中,你可以使用 let self = this 重新定义你的 this,然后使用 self.setState 代替

【讨论】:

这条线在哪里?让自我=这个。内部成功函数?

以上是关于状态未在地理定位功能中使用 setState 进行更新的主要内容,如果未能解决你的问题,请参考以下文章

仅使用 gps 定位模式的 Android 地理围栏监控

React setState未在firestore中执行添加文档承诺解析

自定义提示用户授权使用地理定位功能时的提示语

[作为传递函数,但未在React的子组件中执行

浏览器内地理定位功能:如何在用户拒绝后提示用户重新启用?

在 Android 上使用 PhoneGap 进行地理定位