Search code examples
unit-testingreact-nativejestjsreact-navigation

react-navigation-hooks: How to test useFocusEffect


As I understand it should be done so that useFocusEffect would work as useEffect for testing (mock). I use useFocusEffect for fetchData:

useFocusEffect(
  useCallback(() => {
    fetchData();
  }, [fetchData]),
);

Error message: react-navigation hooks require a navigation context but it couldn't be found. Make sure you didn't forget to create and render the react-navigation app container. If you need to access an optional navigation object, you can useContext(NavigationContext), which may return

Package versions:

"jest": "^24.9.0",
"react-native": "0.61.2",
"react-navigation": "^4.0.10",
"react-navigation-hooks": "^1.1.0",
"@testing-library/react-native": "^4.0.14",

Solution

  • Assuming you're rendering your component in your test, you need to wrap it in a fake <NavigationContext>. Doing so lets useFocusEffect look up the things it needs to determine if the component has been focused by your app's navigation.

    This example uses render from react-native-testing-library. I think it's analogous to other rendering methods though.

    import { NavigationContext } from "@react-navigation/native"
    import { render } from "react-native-testing-library"
    
    // fake NavigationContext value data
    const navContext = {
      isFocused: () => true,
      // addListener returns an unscubscribe function.
      addListener: jest.fn(() => jest.fn())
    }
    
    // MyComponent needs to be inside an NavigationContext, to allow useFocusEffect to function.
    const { toJSON } = render(
      <NavigationContext.Provider value={navContext}>
        <MyComponent />
      </NavigationContext.Provider>
    )