如何在next.js中使用windows.matchMedia与样式组件主题?

dl5txlt9  于 2023-08-04  发布在  Windows
关注(0)|答案(1)|浏览(126)

我有一个主题:

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%
我该怎么做?

hujrc8aj

hujrc8aj1#

你可以做一个钩子:

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;

字符串
然后在你的__app.js中导入它并将其添加到你的主题中:

import MediaQuery from 'hooks/useMedia';

const isCompact = MediaQuery(576);
const useTheme = { ...theme, isCompact };

<ThemeProvider theme={useTheme}>
  ... my app
</ThemeProvider>

相关问题