React: Hooks: useContext mit useState wird nicht aktualisiert

Erstellt am 26. Jan. 2019  ·  3Kommentare  ·  Quelle: facebook/react

Möchten Sie eine Funktion anfordern oder einen Fehler melden?

Es scheint ein Fehler zu sein . 😕

Wie ist das aktuelle Verhalten?

Verschachtelter Kontextanbieter und useContext Hooks scheinen in Konflikt zu stehen, Updates werden verworfen.

Was ist das erwartete Verhalten?

Wenn Sie eine Verbindung zu einem Kontext herstellen, sollte diese aktualisiert werden, wenn sich value ändert.

Welche Versionen von React und welcher Browser / welches Betriebssystem sind von diesem Problem betroffen?

  • reagieren : 18.8.0-alpha.1 (auch reproduziert auf 16.7.0-alpha.0 )
  • Browser : chrome 71
  • Betriebssystem : macOS Sierra

mehr Details

Während Sie an einer Bereinigung einer localStorage- "Verbindung" arbeiten,
Ich habe versucht, 2 Artikel ( [1] & [2] ) aus der offiziellen Reaktionsdokumentation zu mischen. Ich habe sie mit Hooks implementiert, aber der Wert scheint nicht durchzugehen.

Ich habe eine optimierte Demo für Codesandbox [3] .

Die eigentliche Implementierung besteht nur noch aus ein paar Zeilen (Parsen und Stringisieren von JSON).

Problemumgehungen, die ich gefunden habe:

  • Wenn ich bei jedem Rendern eine neue Funktion um die Funktion setValue erstelle, funktioniert dies tatsächlich.

    • Dies widerspricht jedoch dem Ratschlag zu [1] , die Schaffung neuer Werte zu vermeiden.

  • Migrieren Sie es in eine Klasse und verwenden Sie componentDidUpdate anstelle von useEffect .

    • Ich benutze das gerade, da es funktioniert. Einschließlich Speichern eines Verweises auf die Funktion im Zustand.


Gibt es etwas, das mit dem folgenden Code nicht funktionieren sollte? Der Effekt wird mit den Änderungen ausgelöst.
Der Wert wird jedoch nicht für die Komponenten aktualisiert, die über Hook verbraucht werden. siehe Repro-Code [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-um zu vermeiden, dass Rückrufe weitergegeben werden
[2] : https://reactjs.org/docs/context.html#updating -context-from-a-verschachtelte-Komponente
[3] : https://codesandbox.io/s/0yzjr8vnrv


hlcecpq

Question

Hilfreichster Kommentar

Ich habe eine optimierte Demo für Codesandbox [3] erstellt.

Für mich sieht es so aus, als ob sich Ihre useContext -Anrufe in derselben Komponente befinden wie Provider . In diesem Sinne lesen sie den Kontext über dem Provider (dem Standard).

Der Wert des Anbieters beeinflusst nur den Kontext für Komponenten innerhalb des Anbieters.

Übrigens, wenn Sie nicht versucht hätten, die Hooks-Regeln mit Code wie [A, B].map(useContext) zu betrügen, hätten Sie das vielleicht früher bemerkt ;-)

Alle 3 Kommentare

Ich habe eine optimierte Demo für Codesandbox [3] erstellt.

Für mich sieht es so aus, als ob sich Ihre useContext -Anrufe in derselben Komponente befinden wie Provider . In diesem Sinne lesen sie den Kontext über dem Provider (dem Standard).

Der Wert des Anbieters beeinflusst nur den Kontext für Komponenten innerhalb des Anbieters.

Übrigens, wenn Sie nicht versucht hätten, die Hooks-Regeln mit Code wie [A, B].map(useContext) zu betrügen, hätten Sie das vielleicht früher bemerkt ;-)

Hey Dan! danke für die schnelle antwort (: habe es gerade für mich behoben.

Übrigens: useContext (über useStorage ) befindet sich innerhalb von App , was _in_ innerhalb von Provider in der Funktion ReactDOM.render . (Vielleicht habe ich das Beispiel zu kurz gemacht, um diese Verschachtelung zu sehen).


Lösung :

Ich habe es gerade gelöst, indem ich diese skurrile .map -Zeile geändert habe: Ich habe den observedBits -Parameter verpasst, der weitergegeben wurde. Ich habe es hier in den Issues / PRs gelesen, aber vergessen bei der Implementierung und endete mit dem Verhalten durcheinander.

Aaah, du hast recht, ich habe dein Beispiel falsch verstanden. Ja, observedBits ist hier das Problem. Scheint eine Falle zu sein, aber dann empfehlen wir auch nicht, useContext jemals dynamisch anzurufen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen