diff --git a/packages/core/src/__tests__/useNavigationCache.test.tsx b/packages/core/src/__tests__/useNavigationCache.test.tsx index 490ddbaf..76801835 100644 --- a/packages/core/src/__tests__/useNavigationCache.test.tsx +++ b/packages/core/src/__tests__/useNavigationCache.test.tsx @@ -1,7 +1,10 @@ import * as React from 'react'; -import { render } from 'react-native-testing-library'; +import { render, act } from 'react-native-testing-library'; import useEventEmitter from '../useEventEmitter'; import useNavigationCache from '../useNavigationCache'; +import useNavigationBuilder from '../useNavigationBuilder'; +import BaseNavigationContainer from '../BaseNavigationContainer'; +import Screen from '../Screen'; import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter'; beforeEach(() => (MockRouterKey.current = 0)); @@ -56,3 +59,136 @@ it('preserves reference for navigation objects', () => { root.update(); }); + +it('returns correct value for isFocused', () => { + const TestNavigator = (props: any): any => { + const { state, descriptors } = useNavigationBuilder(MockRouter, props); + + return state.routes.map(route => descriptors[route.key].render()); + }; + + let navigation: any; + + const Test = (props: any) => { + navigation = props.navigation; + + return null; + }; + + render( + + + {() => null} + + {() => null} + + + ); + + expect(navigation.isFocused()).toBe(false); + + act(() => navigation.navigate('second')); + + expect(navigation.isFocused()).toBe(true); + + act(() => navigation.navigate('third')); + + expect(navigation.isFocused()).toBe(false); + + act(() => navigation.navigate('second')); + + expect(navigation.isFocused()).toBe(true); +}); + +it('returns correct value for isFocused after changing screens', () => { + const TestRouter = ( + options: Parameters[0] + ): ReturnType => { + const router = MockRouter(options); + + return { + ...router, + + getStateForRouteNamesChange(state, { routeNames }) { + const routes = routeNames.map( + name => + state.routes.find(r => r.name === name) || { + name, + key: name, + } + ); + + return { + ...state, + routeNames, + routes, + index: routes.length - 1, + }; + }, + }; + }; + + const TestNavigator = (props: any): any => { + const { state, descriptors } = useNavigationBuilder(TestRouter, props); + + return state.routes.map(route => descriptors[route.key].render()); + }; + + let navigation: any; + + const Test = (props: any) => { + navigation = props.navigation; + + return null; + }; + + const root = render( + + + {() => null} + + {() => null} + + + ); + + expect(navigation.isFocused()).toBe(false); + + root.update( + + + {() => null} + {() => null} + + + + ); + + expect(navigation.isFocused()).toBe(true); + + root.update( + + + {() => null} + {() => null} + {() => null} + + + + ); + + expect(navigation.isFocused()).toBe(true); + + root.update( + + + {() => null} + {() => null} + + {() => null} + + + ); + + expect(navigation.isFocused()).toBe(false); +}); diff --git a/packages/core/src/useNavigationCache.tsx b/packages/core/src/useNavigationCache.tsx index 8e63104d..ca0ffefe 100644 --- a/packages/core/src/useNavigationCache.tsx +++ b/packages/core/src/useNavigationCache.tsx @@ -63,7 +63,7 @@ export default function useNavigationCache< }; cache.current = state.routes.reduce>( - (acc, route, index) => { + (acc, route) => { const previous = cache.current[route.key]; if (previous) { @@ -110,7 +110,7 @@ export default function useNavigationCache< isFocused: () => { const state = getState(); - if (index !== state.index) { + if (state.routes[state.index].key !== route.key) { return false; }