web-dev-qa-db-fra.com

Gatsby: React Rendu conditionnel basé sur la fenêtre.innerWidth Mauvaise conduite

Le rendu conditionnel des composants basés sur window.innerWidth Semble ne pas fonctionner comme prévu juste dans le Production Construction du site Web basé sur Gatsby.

Le crochet que j'utilise pour vérifier la largeur de la fenêtre, avec la vérification supplémentaire de la fenêtre Global pour éviter les erreurs de construction de la production de gatsby-nœud, est la suivante:

import { useState, useEffect } from 'react'

const useWindowWidth = () => {
  const windowGlobal = typeof window !== 'undefined'

  if(windowGlobal) {
    const [width, setWidth] = useState(window.innerWidth)

    useEffect(() => {
      const handleResize = () => setWidth(window.innerWidth)
      window.addEventListener('resize', handleResize)
      return () => {
        window.removeEventListener('resize', handleResize)
      }
    })

    return width
  }
}

export default useWindowWidth

Puis dans mon composant réel, je fais ce qui suit:

IndexPage.Booking = () => {
  const windowWidth = useWindowWidth()

  return (
    <div className="section__booking__wrapper">
      { windowWidth <= mediaQueries.lg && <IndexPage.Cta /> }
      <div className="section__booking-bg" style={{ backgroundImage: `url(${bg})` }}>
        { windowWidth > mediaQueries.lg && <IndexPage.Cta /> }
      </div>
    </div>
  )
}

Cela fonctionne comme il se doit en development mais le production La construction échoue à rendre:

<div className="section__booking-bg" style={{ backgroundImage: `url(${bg})` }}>

Lors du redimensionnement de la fenêtre sous le Mediaqueries.lg (1024), il déclenche ensuite le comportement normal réel ou le rendu de manière conditionnelle des versions mobiles et du bureau du composant.

À Doublecheck Si c'était parce que le rendu déclenche uniquement l'événement resize (ce qu'il ne fonctionne pas comme il fonctionne sur la charge dans development environnement), je suis aussi simplement, de l'intérieur console.log() la valeur de retour et elle est imprimée, in production correctement sur charge.

Il n'y a pas non plus d'erreurs ni d'avertissements dans le Production ou development Construire.

Modifier selon la suggestion de @Phillip

const useWindowWidth = () => {
  const isBrowser = typeof window !== 'undefined'
  const [width, setWidth] = useState(isBrowser ? window.innerWidth : 0)

  useEffect(() => {
    if (!isBrowser) return false

    const handleResize = () => setWidth(window.innerWidth)
    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  })

  return width
}

Il fonctionne désormais lorsque vous le redimensionnez, une fois, sous le seuil Mediaqueries.lg, puis cela fonctionne parfaitement sur le bureau et le mobile, mais pas sur la charge.

8
Mel Macaluso

Ne pas appeler les crochets à l'intérieur des boucles, des conditions ou des fonctions imbriquées ( de React docs )

Réagir des crochets DOIT Exécutez exactement le même ordre sur Tous Rendu. Déplacez votre état en useEffect rappel:

useEffect(() => {
  if (typeof window === 'undefined') return;

  const handleResize = () => setWidth(window.innerWidth);
  window.addEventListener('resize', handleResize);
  return () => {
    window.removeEventListener('resize', handleResize)
  };
});
1
Phillip