如何在 next.js 中使用带有样式组件主题的 window.matchMedia?
Posted
技术标签:
【中文标题】如何在 next.js 中使用带有样式组件主题的 window.matchMedia?【英文标题】:how to use window.matchMedia in next.js with style components theme? 【发布时间】:2022-01-08 09:41:37 【问题描述】:我有一个主题:
const smartPhonePortrait = 320;
const theme =
isCompact:
typeof window !== 'undefined'
? window.matchMedia(`(min-width:$smartPhonePortraitpx)`).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%
如何让它发挥作用?
【问题讨论】:
(min-width: 320px)
媒体查询仍然适用于桌面屏幕尺寸。您需要创建一个不同的查询来匹配桌面屏幕尺寸。
【参考方案1】:
你可以做一个钩子:
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:$widthpx)`);
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>
【讨论】:
以上是关于如何在 next.js 中使用带有样式组件主题的 window.matchMedia?的主要内容,如果未能解决你的问题,请参考以下文章
使用 next.js 和样式化组件重新加载时的 Flash Of Unstyled Text (FOUT)
Next.Js 带有样式组件的 React 应用程序。警告:道具 `className` 不匹配。服务器:“x” 客户端:“y”
如何在 react 和 next js 中使用 Styled 组件创建全局样式,使用 css 文件和 styled 组件的组合是不是更好?