Skip to content

Commit 717c296

Browse files
Merge pull request #7 from aboutbits/match-media-query
Create match media query hook
2 parents 74548c4 + 37c9cdb commit 717c296

5 files changed

Lines changed: 91 additions & 0 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@
4545
"@testing-library/jest-dom": "^5.11.10",
4646
"@testing-library/react": "^11.2.6",
4747
"@testing-library/react-hooks": "^5.1.1",
48+
"@types/css-mediaquery": "^0.1.1",
4849
"@types/jest": "^26.0.22",
4950
"@types/react": "^17.0.3",
5051
"@typescript-eslint/eslint-plugin": "^4.21.0",
5152
"@typescript-eslint/parser": "^4.21.0",
53+
"css-mediaquery": "^0.1.2",
5254
"eslint": "^7.23.0",
5355
"eslint-config-prettier": "^8.1.0",
5456
"eslint-plugin-import": "^2.22.1",

readme.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This package includes different tools that support you with common tasks.
1212
- [useInterval](#useinterval)
1313
- [Async Data](#async-data)
1414
- [LocationProvider](#locationprovider)
15+
- [useMatchMediaQuery](#usematchmediaquery)
1516
- [Build & Publish](#build--publish)
1617
- [Information](#information)
1718

@@ -149,6 +150,20 @@ const MyComponent = () => {
149150
}
150151
```
151152

153+
### useMatchMediaQuery
154+
155+
This hook is based on the `window.matchQuery` API and can be used to find out if a certain media query matches the current window.
156+
157+
```tsx
158+
import { useMatchMediaQuery } from '@aboutbits/react-toolbox'
159+
160+
const TestComponent = () => {
161+
const matches = useMatchMediaQuery('(min-width : 500px)')
162+
if (matches) return <div>visible</div>
163+
return null
164+
}
165+
```
166+
152167
## Build & Publish
153168

154169
To publish the package commit all changes and push them to main. Then run one of the following commands locally:

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
LocationContext,
77
LocationContextValue,
88
} from './location-provider/LocationProvider'
9+
import { useMatchMediaQuery } from './useMatchMediaQuery/useMatchMediaQuery'
910

1011
export {
1112
useInterval,
@@ -15,4 +16,5 @@ export {
1516
LocationProvider,
1617
LocationContext,
1718
LocationContextValue,
19+
useMatchMediaQuery,
1820
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import isMatching from 'css-mediaquery'
3+
import { render, RenderResult } from '@testing-library/react'
4+
import { useMatchMediaQuery } from '../useMatchMediaQuery'
5+
6+
beforeEach(() => {
7+
// mock window.matchMedia (use 'css-mediaquery')
8+
window.matchMedia = jest.fn().mockImplementation((query) => {
9+
return {
10+
addListener: jest.fn(),
11+
media: query,
12+
matches: isMatching.match(query, {
13+
width: 500,
14+
}),
15+
}
16+
})
17+
})
18+
19+
const TestComponent = ({ query }: { query: string }) => {
20+
const isMatched = useMatchMediaQuery(query)
21+
if (isMatched) return <div>visible</div>
22+
return <div>hidden</div>
23+
}
24+
25+
function renderTestComponent(query: string): RenderResult {
26+
return render(<TestComponent query={query} />)
27+
}
28+
29+
describe('useReactSimpleMatchMedia', () => {
30+
it('should be visible when min width matches', () => {
31+
const { getByText } = renderTestComponent('(min-width : 500px)')
32+
expect(getByText(/visible/i)).toBeInTheDocument()
33+
})
34+
35+
it('should not be visible min does not match', () => {
36+
const { getByText } = renderTestComponent('(min-width : 600px)')
37+
expect(getByText(/hidden/i)).toBeInTheDocument()
38+
})
39+
40+
it('should be visible if between matches', () => {
41+
const { getByText } = renderTestComponent(
42+
'(min-width : 500px) and (max-width: 600px)'
43+
)
44+
expect(getByText(/visible/i)).toBeInTheDocument()
45+
})
46+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useState, useEffect } from 'react'
2+
3+
function useMatchMediaQuery(query: string): boolean | undefined {
4+
if (typeof window !== 'object' || !window.matchMedia) return
5+
6+
const [matches, setMatches] = useState(window.matchMedia(query).matches)
7+
8+
useEffect(() => {
9+
const media = window.matchMedia(query)
10+
11+
if (media.matches !== matches) setMatches(media.matches)
12+
13+
const listener = () => setMatches(media.matches)
14+
15+
if (media.addEventListener) {
16+
media.addEventListener('change', listener)
17+
}
18+
19+
return () =>
20+
media.removeEventListener && media.removeEventListener('change', listener)
21+
}, [matches, query])
22+
23+
return matches
24+
}
25+
26+
export { useMatchMediaQuery }

0 commit comments

Comments
 (0)