web-dev-qa-db-fra.com

Comment utiliser React Hooks Context with multiple values ​​for Providers

Quelle est la meilleure façon de partager certaines valeurs et fonctions globales en réaction?

Maintenant, j'ai un ContextProvider avec tous à l'intérieur:

<AllContext.Provider
  value={{
    setProfile, // second function that changes profile object using useState to false or updated value
    profileReload, // function that triggers fetch profile object from server
    deviceTheme, // object
    setDeviceTheme, // second function that changes theme object using useState to false or updated value
    clickEvent, // click event
    usePopup, // second function of useState that trigers some popup
    popup, // Just pass this to usePopup component
    windowSize, // manyUpdates on resize (like 30 a sec, but maybe can debounce)
   windowScroll // manyUpdates on resize (like 30 a sec, but maybe can debounce)
  }}
>

Mais comme triste dans docs : Étant donné que le contexte utilise l'identité de référence pour déterminer le moment du nouveau rendu, il existe des pièges qui pourraient déclencher des rendus involontaires chez les consommateurs lorsque le parent d'un fournisseur effectue un nouveau rendu. Par exemple, le code ci-dessous restitue tous les consommateurs chaque fois que le fournisseur effectue un nouveau rendu, car un nouvel objet est toujours créé pour la valeur:

C'est mauvais:

<Provider value={{something: 'something'}}>

C'est acceptable:

this.state = {
      value: {something: 'something'},
    };
<Provider value={this.state.value}>

J'imagine qu'à l'avenir, j'aurai peut-être jusqu'à 30 fournisseurs de contexte et ce n'est pas très sympathique: /

Alors, comment puis-je transmettre ces valeurs et fonctions globales aux composants? Je peux juste

  1. Créez un fournisseur de contexte distinct pour tout.
  2. Regroupez quelque chose qui est utilisé ensemble comme profil et ses fonctions, thème et ses fonctions (qu'en est-il de l'identité de référence?)
  3. Peut-être que le groupe ne fonctionne que parce qu'il ne se change pas? qu'en est-il de l'identité de référence?)
  4. Autre moyen le plus simple?

Exemples de ce que j'utilise dans Provider:

// Resize
  const [windowSize, windowSizeSet] = useState({
    innerWidth: window.innerWidth,
    innerHeight: window.innerHeight
  })
// profileReload
const profileReload = async () => {
    let profileData = await fetch('/profile')
    profileData = await profileData.json()

    if (profileData.error)
      return usePopup({ type: 'error', message: profileData.error })

    if (localStorage.getItem('deviceTheme')) {
      setDeviceTheme(JSON.parse(localStorage.getItem('deviceTheme'))) 
    } else if (profileData.theme) {
      setDeviceTheme(JSON.parse(JSON.stringify(profileData.theme)))
    } else {
      setDeviceTheme(settings.defaultTheme) 
    }
    setProfile(profileData)
  }

// Click event for menu close if clicked outside somewhere and other
const [clickEvent, setClickEvent] = useState(false)
const handleClick = event => {
  setClickEvent(event)
}
// Or in some component user can change theme just like that
setDeviceTheme({color: red})
5
RTW

Vous pouvez toujours les combiner! Si vous êtes préoccupé par les performances, vous pouvez créer l'objet plus tôt. Je ne sais pas si les valeurs que vous utilisez changent, sinon, c'est assez simple:

state = {
  allContextValue: {
    setProfile,
    profileReload,
    deviceTheme,
    setDeviceTheme,
    clickEvent,
    usePopup,
    popup,
    windowSize
  }
}

render() {
  return <AllContext.Provider value={this.state.allContextValue}>...</AllContext>;
}

Chaque fois que vous souhaitez mettre à jour l'une des valeurs que vous devez faire, j'aime bien ceci:

this.setState({
  allContextValue: {
    ...this.state.allContextValue,
    usePopup: true,
  },
});

Ce sera à la fois performant et relativement facile aussi :) Le fractionnement de ceux-ci pourrait accélérer un peu, mais je ne le ferais que lorsque vous constaterez qu'il est réellement lent, et uniquement pour des parties de votre contexte qui auraient un beaucoup de consommateurs.

Pourtant, si votre valeur ne change pas beaucoup, il n'y a vraiment rien à craindre.

0
Michiel Dral