Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
[react-hooks] initialize Media hooks with correct matches value
Browse files Browse the repository at this point in the history
  • Loading branch information
melnikov-s committed Jul 12, 2024
1 parent 9613191 commit de28197
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-days-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/react-hooks': major
---

Media hooks initialized with correct matches value
12 changes: 10 additions & 2 deletions packages/react-hooks/src/hooks/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ 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,
{ssr, ssrValue}: {ssr?: boolean; ssrValue?: boolean} = {
ssr: false,
ssrValue: false,
},
) => {
const [match, setMatch] = useState(() =>
ssr ? Boolean(ssrValue) : window.matchMedia(query).matches,
);

useEffectHook(() => {
if (!window || !window.matchMedia) {
Expand Down
44 changes: 42 additions & 2 deletions packages/react-hooks/src/hooks/tests/media.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand All @@ -17,8 +20,17 @@ describe('useMedia and useMediaLayout', () => {
['useMedia', useMedia],
['useMediaLayout', useMediaLayout],
])('%s', (_, useEffectHook) => {
function MockComponent({mediaQuery}: {mediaQuery: string}) {
const matchedQuery = useEffectHook(mediaQuery);
function MockComponent({
mediaQuery,
ssr = false,
ssrValue = false,
}: {
mediaQuery: string;
ssr?: boolean;
ssrValue?: boolean;
}) {
const matchedQuery = useEffectHook(mediaQuery, {ssr, ssrValue});
matches.push(matchedQuery);
const message = matchedQuery ? 'matched' : 'did not match';
return <div>{message}</div>;
}
Expand Down Expand Up @@ -66,6 +78,33 @@ describe('useMedia and useMediaLayout', () => {
);

const mockComponent = mount(<MockComponent mediaQuery="print" />);
expect(matches).toStrictEqual([true]);
expect(mockComponent.text()).toContain('matched');
});

it('initial render with ssrValue true', () => {
matchMedia.setMedia(() =>
mediaQueryList({
matches: true,
}),
);

const mockComponent = mount(
<MockComponent mediaQuery="print" ssr ssrValue={true} />,

Check failure on line 93 in packages/react-hooks/src/hooks/tests/media.test.tsx

View workflow job for this annotation

GitHub Actions / Test (Node 18, React 18)

Value must be omitted for boolean attribute `ssrValue`

Check failure on line 93 in packages/react-hooks/src/hooks/tests/media.test.tsx

View workflow job for this annotation

GitHub Actions / Test (Node 20, React 18)

Value must be omitted for boolean attribute `ssrValue`
);
expect(matches).toStrictEqual([true]);
expect(mockComponent.text()).toContain('matched');
});

it('initial render with ssrValue false', () => {
matchMedia.setMedia(() =>
mediaQueryList({
matches: true,
}),
);

const mockComponent = mount(<MockComponent mediaQuery="print" ssr />);
expect(matches).toStrictEqual([false, true]);
expect(mockComponent.text()).toContain('matched');
});

Expand All @@ -77,6 +116,7 @@ describe('useMedia and useMediaLayout', () => {
);

const mockComponent = mount(<MockComponent mediaQuery="print" />);
expect(matches).toStrictEqual([false]);
expect(mockComponent.text()).toContain('did not match');
});

Expand Down

0 comments on commit de28197

Please sign in to comment.