簡體   English   中英

異步調用后在 React 中重新渲染狀態

[英]Rerendering state in React after async call

我正在嘗試在調用 Geolocation API 后將用戶的當前城市加載到頁面上。 但是,調用 geolocation 函數的主要組件是在位置 Promise 返回之前將狀態設置為 undefined。

我的目標是設置用戶當前位置的狀態。 但是,當我在 React 組件中調用 geolocate() 時, state.city 被設置為 undefined 因為它不等待 geolocation 函數返回任何內容。

我的地理定位功能:

const geolocate = async () => {
    if (!navigator.geolocation) {
        alert('Geolocation is not supported by your browser. Please search for a location to look for weather');
    } else {
        getCoordinates().then((position) => {
            getCityByCoords(position)
            .then((response) => {
                return response;
            })
            .catch(err => console.log(err));
        })
        .catch(err => console.log(err));
    }   
}

const getCoordinates = () => {
    return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(
          position => {
            return resolve(position);
          },
          error => reject(error)
        )}
      );
};


// a call to my own API to make a request to Google's geocoding API
// response from this is coming back successfully
const getCityByCoords = (position) => {
    const { latitude, longitude } = position.coords;
    return axios.get('/city', {
        params: {
            lat: latitude,
            lng: longitude
        }
    })
}

我的組件中的函數調用:

 componentDidMount() {
    this.getLocation();
  }

  getLocation() {
    geolocate()
    .then(
      (response) => {
        this.setState({
            city: response,
            isLoaded: true
        })
    },
        (error) => {
            this.setState({
              isLoaded: true,
              error
            });
    })
    .then(() => {
      this.setState({ isLoaded: 'false' });
    })
  }

我認為所有這些異步調用都讓我失望。

首先,您的geolocate函數缺少 return 語句,因此您可以在組件中的函數調用中獲取位置結果。

此外,不要嵌套 Promises,如果你可以返回它們。 在以下代碼段中,我重寫了您的geolocate函數:

const geolocate = async () => {
  if (!navigator.geolocation) {
    // better would be to throw an error here, so you can handle them in your component (or wherever else)
    alert(
      "Geolocation is not supported by your browser. Please search for a location to look for weather"
    );
  } else {
    // return was missing
    return getCoordinates()
      .then(position => getCityByCoords(position))
      .catch(err => console.log(err));
  }
};

之后,讓我們解決您的問題:您沒有在構造函數中初始化您的狀態,因此在第一次渲染時,它對cityisLoaded一無所知。

如果您將狀態的初始化放入構造函數中,它應該打印您想要的城市,或一個簡單的“等待”段落:


class Geo extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      city: "",
      isLoaded: false
    };
  }

  componentDidMount() {
    this.getLocation();
  }

  getLocation() {
    geolocate()
      .then(
        response => {
          this.setState({
            city: response,
            isLoaded: true
          });
        },
        error => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
      .then(() => {
        this.setState({ isLoaded: "false" });
      });
  }

  render() {
    if (!this.state.isLoaded) {
      return <div>Waiting for Geolocation...</div>;
    }
    return <div>Geolocation: {this.state.city}</div>;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM