From e52efbce550f78a094b4d8d33b9f448f343ee97a Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Wed, 6 Oct 2021 04:13:49 -0500 Subject: [PATCH] fix: memoize useNavigation hook --- src/hooks/__tests__/useNavigation.test.tsx | 55 ++++++++++++++++++---- src/hooks/useNavigation.ts | 7 ++- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/hooks/__tests__/useNavigation.test.tsx b/src/hooks/__tests__/useNavigation.test.tsx index b10132a..f9e95c5 100644 --- a/src/hooks/__tests__/useNavigation.test.tsx +++ b/src/hooks/__tests__/useNavigation.test.tsx @@ -4,19 +4,27 @@ import { RouterProvider } from '../../components/RouterProvider'; import type { RouterContextProps } from '../../types'; import { useNavigation } from '../useNavigation'; -const ContextWrapper = ({ children }: { children: ReactNode }) => { +const defaultMockHistory = { + block: 'mockHistoryBlock', + go: 'mockHistoryGo', + goBack: 'mockHistoryBack', + goForward: 'mockHistoryForward', + push: 'mockHistoryPush', + replace: 'mockHistoryReplace', +}; + +const ContextWrapper = ({ + children, + history = defaultMockHistory, +}: { + children?: ReactNode; + history?: unknown; +}) => { return ( @@ -48,4 +56,33 @@ describe('useNavigation()', () => { replace: 'mockHistoryReplace', }); }); + + it('should return memoized function', () => { + const { result, rerender } = renderHook(() => useNavigation(), { + wrapper: ContextWrapper, + }); + + const firstResult = result.current; + + rerender(); + + expect(firstResult).toEqual(result.current); + }); + + it('should mutate navigation if history object changes', () => { + const { result, rerender } = renderHook(() => useNavigation(), { + wrapper: ContextWrapper, + }); + + const firstResult = result.current; + + rerender({ + history: { + ...defaultMockHistory, + block: 'foo', + }, + }); + + expect(firstResult).not.toEqual(result.current); + }); }); diff --git a/src/hooks/useNavigation.ts b/src/hooks/useNavigation.ts index a3ef995..3d14cf6 100644 --- a/src/hooks/useNavigation.ts +++ b/src/hooks/useNavigation.ts @@ -1,5 +1,5 @@ import type { History } from 'history'; -import { useContext } from 'react'; +import { useContext, useMemo } from 'react'; import { isRouterContext, RouterContext } from '../context/RouterContext'; import type { RouterContextProps, State } from '../types'; @@ -23,5 +23,8 @@ export const useNavigation = (): UseNavigation => { const { goBack, block, goForward, go, push, replace } = context.history; - return { back: goBack, block, forward: goForward, go, push, replace }; + return useMemo( + () => ({ back: goBack, block, forward: goForward, go, push, replace }), + [goBack, block, goForward, go, push, replace] + ); };