Search code examples
react-nativenavigationreact-navigation-v6

useEffect is not called when navigating back to screen - React Navigation


I have a screen that makes a call to an api to fetch some data which is then displayed

An issue that I am seeing is that when I navigate away from the screen (I am using react-navigation 6.x) and then go back to it useEffect() is not being called

From what I have read so far, this is down to the value of userId not changing (I think i need to do some more reading around the useEffect() hook to understand better, maybe someone will help clear things up with this question)

import React, {useState, useEffect, useContext} from 'react';
import AppContext from '../../components/AppContext.js';

export const CreateNewEvent = () => {
  const globalContext = useContext(AppContext);
  const userId = globalContext.userInfo.id;

  useEffect(() => {
    const body = JSON.stringify({userId});
    fetch(eventTypesUrl, {
      method: 'POST',
      headers: {'Content-Type': 'application/json', Accept: 'application/json'},
      body: body,
    })
      .then(response => response.json())
      .then(json => setEventTypeData(json))
      .catch(error => console.error(error))
      .finally(() => setLoading(false));
    }, [userId]);

}

So in my scenario I am on Screen 1 (Here i can create an event which makes a request to get all event types and loads them into a select menu)

When I navigate to Screen 2 (to create an event type) and then back to Screen 1, the useEffect() hook is not called resulting in being unable to see the event type I have just created (hope that makes sense).. also notice that any data entered in Screen 1 previously still remains

I have come across this post which appears to be what I am dealing with, just a little unsure how to implement with my setup

How can I ensure that Screen 2 makes the api call when i go back and that all previous form data is cleared out?

Thanks


Solution

  • At the core, React Navigation does not rerender the screen when a user navigates back to that screen for performance optimization and avoids unnecessary rerenders.

    When required, They provide a useful hook to detect when screen is focused and run some side effects.

    Let refactor code as below:

    Top-level import 
    import { useFocusEffect } from "@react-navigation/core";
    
    // Run side effects when screen focused, navigated, or visited 
    
    useFocusEffect(
      React.useCallback(() => {
        const body = JSON.stringify({ userId });
        fetch(eventTypesUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json',
          },
          body: body,
        })
          .then(response => response.json())
          .then(json => setEventTypeData(json))
          .catch(error => console.error(error))
          .finally(() => setLoading(false));
    
        return () => {
          // Run  somelogisx when user leave screen,
          // Cleaning caches or cancelling subscriptions
        };
      }, [userId]),
    );
    

    Note: React.useCallback is part of useFocusEffect API. The React Navigation team trying to optimize screen performance with memoization.