React Hook - useMediaQuery


O React Hook personalizado useMediaQuery serve para lidar com consultas de mídia e criar componentes responsivos de maneira simples e eficaz. Ele encapsula a lógica necessária para verificar o estado de uma consulta de mídia e fornece uma maneira fácil de incorporar a responsividade aos seus componentes React.

Vamos explorar a implementação do useMediaQuery passo a passo:

1. Estado interno do Hook

const [match, setMatch] = useState(initialValue);

O estado match armazenará se a consulta de mídia está sendo correspondida no momento.

2. Debugging com useDebugValue

useDebugValue(`Query: ${queryValue}`, (name) => {
 return name + ' modificado';
});

O useDebugValue é usado para fornecer informações de depuração. Neste caso, exibimos a string da consulta de mídia.

3. Efeito para lidar com alterações na resolução

useEffect(() => {
 let isMounted = true;
 const matchMedia = window.matchMedia(queryValue);
 
 const handleChange = () => {
   if (!isMounted) return;
   setMatch(Boolean(matchMedia.matches));
 };
 
 matchMedia.addEventListener('change', handleChange);
 setMatch(!!matchMedia.matches);
 
 return () => {
   isMounted = false;
   matchMedia.removeEventListener('change', handleChange);
 };
}, [queryValue]);

O useEffect é usado para:

  • Inicializar o estado com o valor inicial da consulta de mídia.
  • Adicionar um ouvinte de alteração para a consulta de mídia.
  • Atualizar o estado quando a consulta de mídia muda.
  • Remover o ouvinte quando o componente é desmontado.

4. Retorno do Hook

return match;

O Hook retorna o valor atual da correspondência da consulta de mídia.

5. Código

import { useDebugValue, useEffect, useState } from 'react';
 
const useMediaQuery = (queryValue, initialValue = false) => {
  const [match, setMatch] = useState(initialValue);
 
  useDebugValue(`Query: ${queryValue}`, (name) => {
    return name + ' modificado';
  });
 
  useEffect(() => {
    let isMounted = true;
    const matchMedia = window.matchMedia(queryValue);
 
    const handleChange = () => {
      if (!isMounted) return;
      setMatch(Boolean(matchMedia.matches));
    };
 
    matchMedia.addEventListener('change', handleChange);
    setMatch(!!matchMedia.matches);
 
    return () => {
      isMounted = false;
      matchMedia.removeEventListener('change', handleChange);
    };
  }, [queryValue]);
 
  return match;
};

Exemplo de uso

O componente Home utiliza o useMediaQuery para determinar diferentes tamanhos de tela e ajustar o estilo com base nesses tamanhos. O fundo do componente é definido dinamicamente com base nas media queries correspondidas.

const Home = () => {
  const huge = useMediaQuery('(min-width: 980px)');
  const big = useMediaQuery('(max-width: 979px) and (min-width: 768px)');
  const medium = useMediaQuery('(max-width: 767px) and (min-width: 321px)');
  const small = useMediaQuery('(max-width: 321px)');
 
  const background = huge ? 'green' : big ? 'red' : medium ? 'yellow' : small ? 'purple' : null;
 
  return <div style={{ fontSize: '60px', background }}>Oi</div>;
};

Neste exemplo, as diferentes consultas de mídia são usadas para determinar quatro tamanhos distintos de tela, cada um associado a uma cor de fundo específica.

Com essa implementação do useMediaQuery, você pode facilmente criar interfaces responsivas adaptadas a diferentes dispositivos e tamanhos de tela, mantendo um código limpo e organizado.

Referências