Home > Enterprise >  React Native useEffect rerenders with initial states
React Native useEffect rerenders with initial states

Time:09-01

In the code below, when the app loads initially "Location changed offline!" is logged every time the location updates. When online is set to true with a TouchableOpacity, the message logged to the console looks like this:

 LOG  true
 LOG  attempting to update location...
 LOG  Location updated in real-time!
 LOG  false
 LOG  Location changed offline!
 LOG  true
 LOG  attempting to update location...
 LOG  true
 LOG  attempting to update location...
 LOG  Location updated in real-time!

For some reason it's randomly changing the state of online back to false, thus causing the "Location changed offline!" to be logged. What could be causing this?

  const [online, setOnline] = useState(false);

  useEffect(() => {
    Geolocation.watchPosition(
      position => {
        console.log(online);
        if (online) {
          console.log('attempting to update location...');
          const payload = {
            lat: position.coords.latitude,
            lng: position.coords.longitude,
            id: 1,
          };

          axios
            .post('http://localhost:3000/location/update', payload)
            .then(res => {
              if (res.status === 200) {
                console.log('Location updated in real-time!');
                return;
              }
            })
            .catch(err => console.log(err.response));
        } else {
          console.log('Location changed offline!');
        }
      },
      err => console.log(err.response)
    );
  }, [online]);

CodePudding user response:

The problem here is that you add a new watcher every time online changes that captures the current value forever.

Adding subscriptions (like Geolocation.watchPosition()) within an effect hook should always be removed in the cleanup function.

useEffect(() => {
  const watchId = Geolocation.watchPosition(async (position) => {
    console.log("online?", online);
    if (online) {
      console.log("attempting to update location...");
      const payload = {
        lat: position.coords.latitude,
        lng: position.coords.longitude,
        id: 1,
      };

      try {
        await axios.post("http://localhost:3000/location/update", payload);

        // no need to check the response status
        console.log("Location updated in real-time!");
      } catch (err) {
        console.warn(err.toJSON()); // Axios helper, much nicer to look at
      }
    } else {
      console.log("Location changed offline!");
    }
  }, console.error);

  // return a cleanup function
  return () => {
    Geolocation.clearWatch(watchId);
  };
}, [online]);

See https://reactnative.dev/docs/0.63/geolocation#clearwatch

  • Related