如何将 window.matchMedia in next.js 与样式组件主题一起使用?
how to use window.matchMedia in next.js with style components theme?
我有一个主题:
const smartPhonePortrait = 320;
const theme = {
isCompact:
typeof window !== 'undefined'
? window.matchMedia(`(min-width:${smartPhonePortrait}px)`).matches
: false
};
export default theme;
然后我将这个主题添加到我的提供商
_app.js 内部:
import { ThemeProvider } from 'styled-components';
import theme from '../theme';
const App = ({ Component, pageProps, router }) => {
return (
<ThemeProvider theme={theme}>
... my app
</ThemeProvider>
);
};
在我的样式组件中,我这样做:
const Item = styled.div`
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 0;
flex-basis: ${(props) => (props.theme.isCompact ? '100%' : '48%')};
`;
这适用于第一次渲染,但当我更改屏幕大小时它不会更新。
如果我在移动设备上,我会得到 flex-basis 100%
但如果我将屏幕尺寸更改为桌面,我不会得到 48%
如何让它发挥作用?
你可以做一个钩子:
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);
}
}, []);
useEffect(() => {
if (typeof window !== 'undefined') {
const media = window.matchMedia(`(max-width:${width}px)`);
media.addListener(updateTarget);
if (media.matches) {
setTargetReached(true);
}
return () => media.removeListener(updateTarget);
}
}, []);
return targetReached;
};
export default useMediaQuery;
然后在您的 __app.js 中导入它并将其添加到您的主题中:
import MediaQuery from 'hooks/useMedia';
const isCompact = MediaQuery (576);
const useTheme = { ...theme, isCompact };
<ThemeProvider theme={useTheme}>
... my app
</ThemeProvider>
我有一个主题:
const smartPhonePortrait = 320;
const theme = {
isCompact:
typeof window !== 'undefined'
? window.matchMedia(`(min-width:${smartPhonePortrait}px)`).matches
: false
};
export default theme;
然后我将这个主题添加到我的提供商
_app.js 内部:
import { ThemeProvider } from 'styled-components';
import theme from '../theme';
const App = ({ Component, pageProps, router }) => {
return (
<ThemeProvider theme={theme}>
... my app
</ThemeProvider>
);
};
在我的样式组件中,我这样做:
const Item = styled.div`
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 0;
flex-basis: ${(props) => (props.theme.isCompact ? '100%' : '48%')};
`;
这适用于第一次渲染,但当我更改屏幕大小时它不会更新。
如果我在移动设备上,我会得到 flex-basis 100%
但如果我将屏幕尺寸更改为桌面,我不会得到 48%
如何让它发挥作用?
你可以做一个钩子:
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);
}
}, []);
useEffect(() => {
if (typeof window !== 'undefined') {
const media = window.matchMedia(`(max-width:${width}px)`);
media.addListener(updateTarget);
if (media.matches) {
setTargetReached(true);
}
return () => media.removeListener(updateTarget);
}
}, []);
return targetReached;
};
export default useMediaQuery;
然后在您的 __app.js 中导入它并将其添加到您的主题中:
import MediaQuery from 'hooks/useMedia';
const isCompact = MediaQuery (576);
const useTheme = { ...theme, isCompact };
<ThemeProvider theme={useTheme}>
... my app
</ThemeProvider>