window.matchMedia не является функцией

#javascript #reactjs #webpack #graphql #gatsby

#javascript #reactjs #webpack #graphql #gatsby

Вопрос:

У меня возникла некоторая проблема с window глобальным объектом в проекте сборки в gatsby. Я использую пользовательский медиа-хук для изменения входа в систему в некоторых разрешениях. Он отлично работает при запуске проекта. Но когда я пытаюсь npm run build построить проект, Webpack выдает ошибку: WebpackError: TypeError: window.matchMedia не является функцией

   const useMedia = (query) => {
    const windowGlobal = typeof window !== 'undefined' amp;amp; window
    const [matches, setMatches] = useState(windowGlobal.matchMedia(query).matches)
    useEffect(() => {
      const media = windowGlobal.matchMedia(query)
      if (media.matches !== matches) setMatches(media.matches)
      const listener = () => setMatches(media.matches)
      media.addEventListener('change', listener)
      return () => media.removeEventListener('change', listener)
    }, [matches, query])

    return matches
  }
  const match = useMedia('(max-width: 575px)')
  const changeLabel = match ? 'Cancel' : 'Add Now'
 

Ответ №1:

Попробуйте:

  const useMedia = (query) => {
    const [matches, setMatches] = useState(typeof window !=='undefined' amp;amp; window.matchMedia(query).matches);

    useEffect(() => {
      const media = windowGlobal.matchMedia(query)
      if (media.matches !== matches) setMatches(media.matches)
      const listener = () => setMatches(media.matches)
      media.addEventListener('change', listener)
      return () => media.removeEventListener('change', listener)
    }, [matches, query])

    return matches
  }
  const match = useMedia('(max-width: 575px)')
  const changeLabel = match ? 'Cancel' : 'Add Now'
 

Вы фиксировали значение windowMedia (такое же, как isBrowser ) с помощью a const , и состояние пыталось установить значение undefined в то время, window когда не было установлено, вы можете упростить, установив состояние только тогда, когда window определено.

Ответ №2:

Вы делаете это неправильно. Вы устанавливаете для const windowGlobal значение true / false, а затем используете его в useState(windowGlobal...) , что означает, что windowGlobal — это bool, а не функция. Используйте window напрямую, как в моем примере ниже:

 const windowGlobal = typeof window !== 'undefined' amp;amp; window
const [matches, setMatches] = useState(windowGlobal.matchMedia(query).matches)
 

Я бы пошел с созданием, если установлено окно, затем выполните код.

 const useMedia = (query) => {
  const [matches, setMatches] = useState(windowGlobal.matchMedia(query).matches)
  
  const isBrowser = () => typeof window !== 'undefined' amp;amp; window;
  
  useEffect(() => {
    if (isBrowser()) {
      const media = window.matchMedia(query)
      if (media.matches !== matches) setMatches(media.matches)
      const listener = () => setMatches(media.matches)
      media.addEventListener('change', listener)

      return () => media.removeEventListener('change', listener)
    }
  }, [matches, query])

  return matches
}
const match = useMedia('(max-width: 575px)')
const changeLabel = match ? 'Cancel' : 'Add Now'
 

Комментарии:

1. какое решение вы можете посоветовать ?

2. @Bavarius Я обновил пример того, как я это сделаю

3. когда я запускаю с npm run этим все в порядке, но когда я хочу создать ту же ошибку WebpackError: TypeError: windowGlobal.matchMedia is not a function

4. Вам нужно использовать window вместо windowGlobal, который является Bool в вашем коде. Я обновил свой пример в useEffect. Используйте только window там