Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useMediaQuery Hook only sets value on initial redner #1846

Closed
AdlerJS opened this issue Apr 10, 2024 · 2 comments · Fixed by #1853
Closed

useMediaQuery Hook only sets value on initial redner #1846

AdlerJS opened this issue Apr 10, 2024 · 2 comments · Fixed by #1853

Comments

@AdlerJS
Copy link

AdlerJS commented Apr 10, 2024

Issue:

Per the README the following code should trigger true or false if media query elements are within the 'md' range.

  const { breakpoints } = useTheme();
  const isMd = useMediaQuery(breakpoints.only('sm'));
  console.log('HIT***', isMd);

This works as expected for initial render but if the user resizes the hook does not update.

Steps to Reproduce
1.) Place the code in a component and refresh the window. Observe that the console log runs
2.) Resize window to small or large
3.) Observe that the hook / console log doenst update

@AdlerJS
Copy link
Author

AdlerJS commented Apr 10, 2024

@mg901 Using your code as a baseline I created a hook locally in my project that seems to be working.

import { useState, useLayoutEffect, useEffect } from 'react';

const IS_BROWSER = typeof window !== 'undefined';
const useEnhancedEffect = IS_BROWSER ? useLayoutEffect : useEffect;

function getInitialState(query: string): boolean {
  return window.matchMedia(query).matches;
}

/**
 * Custom hook for handling media queries.
 * @param {string} query - The media query to match.
 * @returns {boolean} - `true` if the media query matches, otherwise `false`.
 */
export function useMediaQuery(query: string): boolean {
  const [state, setState] = useState(IS_BROWSER && getInitialState(query));

  useEnhancedEffect(() => {
    let mounted = true;
    const mediaQueryList = window.matchMedia(query.replace(/^@media\s*/, ''));

    const handleChange = () => {
      if (!mounted) return;
      setState(mediaQueryList.matches);
    };

    mediaQueryList.addEventListener('change', handleChange);

    setState(mediaQueryList.matches);

    return () => {
      mounted = false;
      mediaQueryList.removeEventListener('change', handleChange);
    };
  }, [query]);

  return state;
}

If you want I can open a PR for this if this code looks ok with you

@mg901
Copy link
Owner

mg901 commented Apr 12, 2024

Hi, @AdlerJS. Thank you for your bug report. Please, install the latest version of the styled-breakpoints to fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants