diff --git a/docs/useCookie.md b/docs/useCookie.md index 92bf9f63e7..efee285e22 100644 --- a/docs/useCookie.md +++ b/docs/useCookie.md @@ -3,6 +3,9 @@ React hook that returns the current value of a `cookie`, a callback to update the `cookie` and a callback to delete the `cookie.` +When `cookieName` changes, the returned value updates to the new cookie's value, or `null` +if it does not exist. The update and delete callbacks also operate on the new cookie. + ## Usage ```jsx diff --git a/src/useCookie.ts b/src/useCookie.ts index 4bdd6c96de..0f2d324054 100644 --- a/src/useCookie.ts +++ b/src/useCookie.ts @@ -1,4 +1,4 @@ -import { useCallback, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import Cookies from 'js-cookie'; const useCookie = ( @@ -6,6 +6,10 @@ const useCookie = ( ): [string | null, (newValue: string, options?: Cookies.CookieAttributes) => void, () => void] => { const [value, setValue] = useState(() => Cookies.get(cookieName) || null); + useEffect(() => { + setValue(Cookies.get(cookieName) || null); + }, [cookieName]); + const updateCookie = useCallback( (newValue: string, options?: Cookies.CookieAttributes) => { Cookies.set(cookieName, newValue, options); diff --git a/tests/useCookie.test.tsx b/tests/useCookie.test.tsx index cc72dc460a..1ea07a44ef 100644 --- a/tests/useCookie.test.tsx +++ b/tests/useCookie.test.tsx @@ -2,7 +2,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import Cookies from 'js-cookie'; import { useCookie } from '../src'; -const setup = (cookieName: string) => renderHook(() => useCookie(cookieName)); +const setup = (cookieName: string) => + renderHook((name) => useCookie(name), { initialProps: cookieName }); it('should have initial value of null if no cookie exists', () => { const { result } = setup('some-cookie'); @@ -66,3 +67,63 @@ it('should delete the cookie on call to deleteCookie', () => { spy.mockRestore(); Cookies.remove(cookieName); }); + +describe('when the cookie name changes', () => { + beforeEach(() => { + Cookies.set('first-cookie', 'first-value'); + Cookies.set('second-cookie', 'second-value'); + }); + + afterEach(() => { + Cookies.remove('first-cookie'); + Cookies.remove('second-cookie'); + }); + + it('should return the value of the new cookie', () => { + const { result, rerender } = setup('first-cookie'); + + rerender('second-cookie'); + + expect(result.current[0]).toBe('second-value'); + }); + + it('should return null when the new cookie does not exist', () => { + const { result, rerender } = setup('first-cookie'); + + rerender('missing-cookie'); + + expect(result.current[0]).toBeNull(); + }); + + it('should read the current value when switching back to a previous cookie', () => { + const { result, rerender } = setup('first-cookie'); + + rerender('second-cookie'); + Cookies.set('first-cookie', 'updated-first-value'); + rerender('first-cookie'); + + expect(result.current[0]).toBe('updated-first-value'); + }); + + it('should update and delete the new cookie without changing the previous cookie', () => { + const { result, rerender } = setup('first-cookie'); + + rerender('second-cookie'); + + act(() => { + result.current[1]('updated-second-value'); + }); + + expect(result.current[0]).toBe('updated-second-value'); + expect(Cookies.get('second-cookie')).toBe('updated-second-value'); + expect(Cookies.get('first-cookie')).toBe('first-value'); + + act(() => { + result.current[2](); + }); + + expect(result.current[0]).toBeNull(); + expect(Cookies.get('second-cookie')).toBeUndefined(); + expect(Cookies.get('first-cookie')).toBe('first-value'); + }); +});