How to run code when returning to a page with React Navigation and React Native.

In a web react app you would use useEffect with an empty dependency for a lifecycle event such as the component mounting (first load). It doesn't work that way if you're using React Navigation with React Native.

This blog post comes from pain I experienced making my first React Native app when I was using React Navigation. My lifecycle effects were firing on the first time a page loaded but if I then returned to that page they did not. I was using them for fetching data regarding orders placed. If I went to the order page, I placed an order and returned to that orders page the up to date order details weren't being fetched, despite the call being in the useEffect.

It turns out the way React Navigation (and most apps apparently) works is that the first time a page is loaded the page is mounted, the lifecycle effects trigger (e.g. useEffect with an empty dependency array), and the code runs. This is the same for React apps on the web also. The difference is with React Navigation if you navigate to a new page the original isn't unloaded. This is done to reserve the page state but it means if you return to that page the lifecycle effects don't trigger on subsquent visits. This was causing my unexpected behaviour.

The solution is that React Navigation has built its own hook for exactly this occasion. The hook is called useFocusEffect and you can find it detailed in the docs here:

A basic example would look like this; subscribing to a stream on page load and removing the subscription when the page is unloaded

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

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

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

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

  return <ProfileContent user={user} />;

Just a little gotcha' when using React Navigation.

Thanks for reading