1

I am busy learning javascript, and it, as well as react, nodejs and npm are all brand new concepts to me, so bear with me.

I have managed to piece together an application which returns the weather for my location by following this tutorial: https://www.freecodecamp.org/news/learn-react-by-building-a-weather-app/

I run npm and then I am able to view the executed app on localhost:3000/

When I make changes to the .js application (I use atom), npm compiles the new code and it works perfectly.

But when I reload the web page it doesn't work (returns nothing).

Looking at the console in Chrome, when I do a compile, it immediately gets my location and the API call to openweathermap works (it includes the location in the call of course).

But when I reload the page, it seems like the location is not successfully fetched, and then obviously it cannot return anything. What's weird is that it seems to attempt it 3 times, and the second time it works, but the first and third time it fails.

Here is the piece of code where the issue seems to lie and I also attached an image of what the app looks like when it WORKS, and what the console shows when it does NOT work (when reloading). console when I reload when it works

useEffect(() => {
    const fetchData = async () => {
      navigator.geolocation.getCurrentPosition(function(position) {
        setLat(position.coords.latitude);
        setLong(position.coords.longitude);
      });

      await fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${lat}&lon=${long}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
      .then(res => res.json())
      .then(result => {
        setData(result)
        console.log(d)                      // (GL)
        console.log("Latitude is:", lat)    // (GL)
        console.log("Longitude is:", long)  // (GL)
        console.log(result);
      });
    }
    fetchData();
  }, [lat,long])
user2725402
  • 4,349
  • 7
  • 24
  • 23
  • Stop working in [Strict-mode](https://reactjs.org/docs/strict-mode.html)... it's useless and problematic – vsync Sep 20 '22 at 13:37
  • Makes **no sense** writing `await fetch` when you're using the *promise* syntax `then`... pick one of the code styles. – vsync Sep 20 '22 at 13:41

2 Answers2

1

You should remove the react-strict wrapper component.

Also - makes no sense writing await fetch when you're using the promise syntax then...

You need so split the logic within the useEffect because you are setting a state within the getCurrentPosition callback, and at the same time listen to a state change in the dependency array of that useEffect...

// this useEffect will only fire when the component mounts (once)
useEffect(() => {
    navigator.geolocation.getCurrentPosition(location => {
        // you should validate the response before setting the state...
        setLat(location.coords.latitude);
        setLong(location.coords.longitude);
    });
}, [])

// this useEffect will be called one the component mounts + when any dependency changes (lat/long)
useEffect(() => {
    fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${lat}&lon=${long}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
        .then(res => res.json())
        .then(result => {
            setData(result)
            console.log(d)                      // (GL)
            console.log("Latitude is:", lat)    // (GL)
            console.log("Longitude is:", long)  // (GL)
            console.log(result);
    });
}, [lat, long])

Even though this is correct, this is considered bad code, and should be split between separate files for dealing with the API/actions/utility methods..etc.

vsync
  • 118,978
  • 58
  • 307
  • 400
  • I have (as a starting point) removed strict mode. I still wanted to work through the rest of your feedback to make the changes (and I still will), but after removing strict mode everything works fine! can you perhaps explain why? – user2725402 Sep 20 '22 at 14:04
  • The error message is very clear & helpful: ***"findDOMNode is deprecated in StrictMode"*** and you should have Googled that to learn more about it and could have found a [wealth of answers](https://stackoverflow.com/q/60903335/104380). I suspect it's a 3rd-party package which is using deprecated code. Impossible to know which from your screenshot. (you probably need to check the console in development-mode and not production-code to understand from the stack where is the root cause) – vsync Sep 20 '22 at 20:04
0

The problem is that your fetchData function is an async function. So when you call fetchData, you'll need a .then() to make sure that it gets the result. Also your useEffect inner function should be async

useEffect(async () => {
    const fetchData = async () => {
      navigator.geolocation.getCurrentPosition(function(position) {
        setLat(position.coords.latitude);
        setLong(position.coords.longitude);
      });

      await fetch(`${process.env.REACT_APP_API_URL}/weather/?lat=${lat}&lon=${long}&units=metric&APPID=${process.env.REACT_APP_API_KEY}`)
      .then(res => res.json())
      .then(result => {
        setData(result)
        console.log(d)                      // (GL)
        console.log("Latitude is:", lat)    // (GL)
        console.log("Longitude is:", long)  // (GL)
        console.log(result);
      });
    }
    fetchData().then(result => {
        //do stuff (or await this fetch data)
    });
  }, [lat,long])
Eric Yang
  • 2,678
  • 1
  • 12
  • 18
  • **No** it's not that at all. incorrect. no need for `async` in `useEffect(async () => {` – vsync Sep 20 '22 at 13:39