clearTimeout or clearInterval in React Native views with React Navigation

When working on a regular React app, it is common to initialize some hooks after the component is mounted, and unbind them after the component is unmounted. However, while working on a React Native app, you might have noticed that the views are actually not unmounted, and as such your bound events and background tasks continue to run from the previous view. Here’s what you can do.

useFocusEffect to the rescue

useFocusEffect is a special hook from @react-navigation/native, that works in a similar way as React’s useEffect but with a slight difference. It will run in situations when the component is mounted, when the dependencies update, as well as when the view becomes focused.

By knowing now when it runs, you will probably ask how to make sure that all your setTimeouts are cleared. Wrap your callbacks into React’s useCallback. Consider this example from the React Navigation’s documentation:

import { useCallback } from 'react';
import { useFocusEffect } from '@react-navigation/native';

function Profile({ userId }) {
  const [user, setUser] = React.useState(null);

  useFocusEffect(
    useCallback(() => {
      const unsubscribe = API.subscribe(userId, user => setUser(user));

      return () => unsubscribe();
    }, [userId])
  );

  return <ProfileContent user={user} />;
}

This is all you need to transition from useEffect to useFocusEffect. It is very important to remember to have useCallback as it handles caching of your function, and re-running it when dependencies change. Expanding on the example above, here’s how you can use it with setInterval:

import { useCallback, useState } from 'react';
import { useFocusEffect } from '@react-navigation/native';

function Profile({ userId }) {
  const [user, setUser] = useState(null);

  useFocusEffect(
    useCallback(() => {
      const to = setInterval(() => {
        // do something;
        console.log(`User's ID is: ${userId}`);
      }, 5000);

      return () => clearInterval(to);
    }, [userId])
  );

  return <ProfileContent user={user} />;
}

Resources


Did you know that I made an in-browser image converter, where you can convert your images without uploading them anywhere? Try it out and let me know what you think. It's free.

Leave a Comment

Your email address will not be published. Required fields are marked *