简体   繁体   中英

React can't set state with hooks in useEffect()

I'm fairly new to react and decided to develop a simple weather app.Once the page loads I want the app to ask the user for geoloacaion and then display weather data accordingly.

function App() {
  const [weather, setWeather] = useState(null);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(async (position) => {
      let { latitude, longitude } = position.coords;
      const data = await getWeatherByCords(latitude, longitude);
      await setWeather(data); // Line 8
      console.log(weather) //outputs undefined
      setWeather('hhello'); // Line 10
      console.log(weather) //outputs undefined
      let address = await cordsToAddress(latitude, longitude);
    });
  },[]);


  return (
    <div className="App">
      <h3>Weather App</h3>
      <Weather
        data={weather.data}
      />
    </div>
  );
}

export default App;

getWeatherByCords() is just a helper function which sends the request to a weather api and returns its response

I read that useEffect(() => {},[]) hook is equal to componentDidMount() , and as far as I understand is should trigger only when the page is loaded or refreshed, please correct me if I'm wrong

When I try to set weather do the data I received or just for a test to some string,to pass it in the <Weather/> components afterwards, it doesn't work in both cases for some reason and when I try to log weather in console I get undefined in both cases.

Also should I await setting weather(as in line 8) or should I not(as in line 10)?

I read up on hooks and figured it out by myself.

function App() {
  const [weather, setWeather] = useState({});

  useEffect(() => console.log(weather), [weather]);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(async (position) => {
      let { latitude, longitude } = position.coords;
      const data = await getWeatherByCords(latitude, longitude);
      console.log('setting weather');
      setWeather(data);
      let address = await cordsToAddress(latitude, longitude);
    });
  }, []);


  return (
    <div className="App">
      <h3>Weather App</h3>
      <Weather
        data={weather}
      />
    </div>
  );
}

My previous code was actually setting weather, but it was asynchronous so the console.log() didn't capture it. So I wrote a hook that logged weather to console whenever it changed( this question helped me greatly )

useEffect(() => console.log(weather), [weather]);

PS Another problem I encountered was that my component was "refreshing" and sending api requests almost constantly, and as I wanted to send an api request only on page load or refresh I wrapped my navigator code also in useEffect() hook:

useEffect(() => {
  navigator.geolocation.getCurrentPosition(async (position) => {
    // code related to working with apis
  });
}, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM