From d820d1dd0712f38e67d41cb10b9dffca2dba8c87 Mon Sep 17 00:00:00 2001 From: Sergey Melnikov Date: Mon, 4 Jul 2022 12:14:10 -0400 Subject: [PATCH] [react-hooks] initialize Media hooks with correct matches value --- .changeset/four-days-type.md | 5 +++ packages/react-hooks/src/hooks/media.ts | 8 +++- .../src/hooks/tests/media.test.tsx | 44 ++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 .changeset/four-days-type.md diff --git a/.changeset/four-days-type.md b/.changeset/four-days-type.md new file mode 100644 index 0000000000..834386ff32 --- /dev/null +++ b/.changeset/four-days-type.md @@ -0,0 +1,5 @@ +--- +'@shopify/react-hooks': major +--- + +Media hooks initialized with correct matches value diff --git a/packages/react-hooks/src/hooks/media.ts b/packages/react-hooks/src/hooks/media.ts index fa0fcaacb7..bb4ff276e9 100644 --- a/packages/react-hooks/src/hooks/media.ts +++ b/packages/react-hooks/src/hooks/media.ts @@ -3,8 +3,12 @@ import {useState, useEffect, useLayoutEffect} from 'react'; type EffectHook = typeof useEffect | typeof useLayoutEffect; function createUseMediaFactory(useEffectHook: EffectHook) { - return (query: string) => { - const [match, setMatch] = useState(false); + return (query: string, {initialValue}: {initialValue?: boolean}) => { + const [match, setMatch] = useState(() => + initialValue === undefined + ? window.matchMedia(query).matches + : Boolean(initialValue), + ); useEffectHook(() => { if (!window || !window.matchMedia) { diff --git a/packages/react-hooks/src/hooks/tests/media.test.tsx b/packages/react-hooks/src/hooks/tests/media.test.tsx index 3e2d90a761..3971595c7d 100644 --- a/packages/react-hooks/src/hooks/tests/media.test.tsx +++ b/packages/react-hooks/src/hooks/tests/media.test.tsx @@ -5,8 +5,11 @@ import {mount} from '@shopify/react-testing'; import {useMedia, useMediaLayout} from '../media'; describe('useMedia and useMediaLayout', () => { + let matches: boolean[] = []; + beforeEach(() => { matchMedia.mock(); + matches = []; }); afterEach(() => { @@ -17,8 +20,15 @@ describe('useMedia and useMediaLayout', () => { ['useMedia', useMedia], ['useMediaLayout', useMediaLayout], ])('%s', (_, useEffectHook) => { - function MockComponent({mediaQuery}: {mediaQuery: string}) { - const matchedQuery = useEffectHook(mediaQuery); + function MockComponent({ + mediaQuery, + initialValue, + }: { + mediaQuery: string; + initialValue?: boolean; + }) { + const matchedQuery = useEffectHook(mediaQuery, {initialValue}); + matches.push(matchedQuery); const message = matchedQuery ? 'matched' : 'did not match'; return
{message}
; } @@ -66,6 +76,35 @@ describe('useMedia and useMediaLayout', () => { ); const mockComponent = mount(); + expect(matches).toStrictEqual([true]); + expect(mockComponent.text()).toContain('matched'); + }); + + it('initial render with initialValue true', () => { + matchMedia.setMedia(() => + mediaQueryList({ + matches: true, + }), + ); + + const mockComponent = mount( + , + ); + expect(matches).toStrictEqual([true]); + expect(mockComponent.text()).toContain('matched'); + }); + + it('initial render with initialValue false', () => { + matchMedia.setMedia(() => + mediaQueryList({ + matches: true, + }), + ); + + const mockComponent = mount( + , + ); + expect(matches).toStrictEqual([false, true]); expect(mockComponent.text()).toContain('matched'); }); @@ -77,6 +116,7 @@ describe('useMedia and useMediaLayout', () => { ); const mockComponent = mount(); + expect(matches).toStrictEqual([false]); expect(mockComponent.text()).toContain('did not match'); });