From 161d2f146cf57b4a5a529081ebea7e5011431303 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Fri, 3 Jan 2020 14:39:46 +0200 Subject: [PATCH] Add useMediaQuery hook --- snippets/useMediaQuery.md | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 snippets/useMediaQuery.md diff --git a/snippets/useMediaQuery.md b/snippets/useMediaQuery.md new file mode 100644 index 000000000..5314eb1e3 --- /dev/null +++ b/snippets/useMediaQuery.md @@ -0,0 +1,40 @@ +--- +title: useMediaQuery +tags: hooks,state,effect,intermediate +--- + +A hook that returns a value based on a media query. + +- Check if `window` and `window.matchMedia` exist, return `whenFalse` if not. +- Use `window.matchMedia()` to match the given `query`, cast its `matches` property to a boolean and store in a state variable, `match`, using `React.useState()`. +- Use `React.useEffect()` to add a listener for changes and to clean up the listeners after the hook is destroyed. +- Return either `whenTrue` or `whenFalse` based on the value of `match`. + +```jsx +const useMediaQuery = (query, whenTrue, whenFalse) => { + if (typeof window === 'undefined' || typeof window.matchMedia === 'undefined') return whenFalse; + + const mediaQuery = window.matchMedia(query); + const [match, setMatch] = React.useState(!!mediaQuery.matches); + + React.useEffect(() => { + const handler = () => setMatch(!!mediaQuery.matches); + mediaQuery.addListener(handler); + return () => mediaQuery.removeListener(handler); + }, []); + + return match ? whenTrue : whenFalse; +}; +``` + +```jsx +const ResponsiveText = () => { + const text = useMediaQuery( + '(max-width: 400px)', 'Less than 400px wide', 'More than 400px wide' + ); + + return {text}; +} + +ReactDOM.render(, document.getElementById('root')); +```