I have a theme:
const smartPhonePortrait = 320;
const theme = {
isCompact:
typeof window !== 'undefined'
? window.matchMedia(`(min-width:${smartPhonePortrait}px)`).matches
: false
};
export default theme;
And then I add this theme to my provider
inside of _app.js:
import { ThemeProvider } from 'styled-components';
import theme from '../theme';
const App = ({ Component, pageProps, router }) => {
return (
<ThemeProvider theme={theme}>
... my app
</ThemeProvider>
);
};
and in my styled component I do this:
const Item = styled.div`
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 0;
flex-basis: ${(props) => (props.theme.isCompact ? '100%' : '48%')};
`;
This works on first render but when I change screen size it does not update.
If im in mobile I get flex-basis 100%
but if I change the screen size to desktop I dont get 48%
How do I make it work?
What you could do is make a hook:
import { useState, useCallback, useEffect } from 'react';
const useMediaQuery = (width) => {
const [targetReached, setTargetReached] = useState(false);
const updateTarget = useCallback((e) => {
if (e.matches) {
setTargetReached(true);
} else {
setTargetReached(false);
}
}, [setTargetReached]);
useEffect(() => {
if (typeof window !== 'undefined') {
const media = window.matchMedia(`(max-width: ${width}px)`);
media.addEventListener('change', updateTarget);
if (media.matches) {
setTargetReached(true);
}
return () => media.removeEventListener('change', updateTarget);
}
}, []);
return targetReached;
};
export default useMediaQuery;
and in your __app.js
you import it and add it to your theme:
import MediaQuery from 'hooks/useMedia';
const isCompact = MediaQuery(576);
const useTheme = { ...theme, isCompact };
<ThemeProvider theme={useTheme}>
... my app
</ThemeProvider>