React: hooks: useContext avec useState ne se mettant pas à jour

Créé le 26 janv. 2019  ·  3Commentaires  ·  Source: facebook/react

Voulez-vous demander une fonctionnalité ou signaler un bogue ?

semble que ce soit un bug . 😕

Quel est le comportement actuel?

Le fournisseur de contexte imbriqué et les hooks useContext semblent être en conflit, les mises à jour sont supprimées.

Quel est le comportement attendu?

Lors de la connexion à un contexte, il doit se mettre à jour chaque fois que c'est value changements.

Quelles versions de React et quel navigateur / système d'exploitation sont concernés par ce problème?

  • react : 18.8.0-alpha.1 (également reproduit sur 16.7.0-alpha.0 )
  • navigateur : chrome 71
  • os : macOS Sierra

plus de détails

Lors du nettoyage d'une "connexion" localStorage,
J'ai essayé de mélanger 2 articles ( [1] & [2] ) de la documentation officielle de réaction, je l'ai implémenté avec des hooks, mais la valeur ne semble pas passer.

J'ai mis en place une démo simplifiée sur codesandbox [3] .

L'implémentation réelle ne représente que quelques lignes de plus (analyse et stringification en JSON).

Solutions de contournement que j'ai trouvées:

  • Si je crée une nouvelle fonction sur chaque rendu autour de la fonction setValue , cela fonctionne réellement.

    • mais cela va à l'encontre des conseils de [1] pour éviter de créer de nouvelles valeurs.

  • Migrez-le vers une classe et utilisez componentDidUpdate au lieu de useEffect .

    • J'utilise actuellement ceci, car cela fonctionne. Y compris l'enregistrement d'une référence à la fonction dans l'état.


Y a-t-il quelque chose qui ne devrait pas fonctionner sur le code ci-dessous? l'effet est déclenché avec les changements,
mais la valeur n'est pas mise à jour sur les composants qui consomment via hook. voir le code de repro [3]

const createLocalStorage = key => {
    const initialValue = localStorage.getItem(key)
    const ValueContext = createContext(initialValue)
    const SetterContext = createContext(() => {})

    const useStorage = () => [ValueContext, SetterContext].map(useContext)

    const Provider = ({children}) => {
        const [value, setValue] = useState(initialValue)

        useEffect(
            () => {
                console.log('effect', value)
                localStorage.setItem(key, value)
            },
            [value],
        )

        return (
            <ValueContext.Provider value={value}>
                <SetterContext.Provider value={setValue}>
                    {children}
                </SetterContext.Provider>
            </ValueContext.Provider>
        )
    }

    return [Provider, useStorage]
}

[1] : https://reactjs.org/docs/hooks-faq.html#how -to-avoid-passant-callbacks-down
[2] : https://reactjs.org/docs/context.html#updating -context-from-a-nested-component
[3] : https://codesandbox.io/s/0yzjr8vnrv


hlcecpq

Question

Commentaire le plus utile

J'ai mis en place une démo simplifiée sur codesandbox [3].

Il me semble que vos appels useContext sont dans le même composant qu'un Provider . En ce sens, ils lisent le contexte au -

La valeur du fournisseur influence uniquement le contexte des composants à l'intérieur de celui-ci.

Au fait, si vous n'avez pas essayé de tricher les règles de Hooks avec un code comme [A, B].map(useContext) vous l'avez peut-être remarqué plus tôt ;-)

Tous les 3 commentaires

J'ai mis en place une démo simplifiée sur codesandbox [3].

Il me semble que vos appels useContext sont dans le même composant qu'un Provider . En ce sens, ils lisent le contexte au -

La valeur du fournisseur influence uniquement le contexte des composants à l'intérieur de celui-ci.

Au fait, si vous n'avez pas essayé de tricher les règles de Hooks avec un code comme [A, B].map(useContext) vous l'avez peut-être remarqué plus tôt ;-)

salut Dan! merci pour la réponse rapide (: je viens de le réparer pour moi.

btw: useContext (via useStorage ) est à l'intérieur de App , qui _ est_ à l'intérieur de Provider dans la fonction ReactDOM.render . (peut-être ai-je rendu l'exemple trop court pour voir cette imbrication).


solution :

Je viens de le résoudre en modifiant cette ligne bizarre .map : j'ai manqué le paramètre observedBits , qui a fini par être transmis.J'ai lu ici dans les problèmes / PR, mais je l'ai oublié lors de la mise en œuvre, et a fini par jouer avec le comportement.

Aaah tu as raison j'ai mal lu ton exemple. Ouais observedBits est le problème ici. Cela semble être un piège, mais nous ne recommandons pas non plus d'appeler useContext dynamiquement donc ..

Cette page vous a été utile?
0 / 5 - 0 notes