React: ganchos: useContext com useState não atualizando

Criado em 26 jan. 2019  ·  3Comentários  ·  Fonte: facebook/react

Você quer solicitar um recurso ou relatar um bug ?

parece que é um bug . 😕

Qual é o comportamento atual?

O provedor de contexto aninhado e os ganchos useContext parecem estar em conflito, as atualizações são descartadas.

Qual é o comportamento esperado?

Ao conectar a um contexto, ele deve ser atualizado sempre que value muda.

Quais versões do React e quais navegadores / sistemas operacionais são afetados por esse problema?

  • reagir : 18.8.0-alpha.1 (também reproduzido em 16.7.0-alpha.0 )
  • navegador : chrome 71
  • os : macOS Sierra

mais detalhes

Enquanto trabalhava na limpeza de uma "conexão" localStorage,
Tentei misturar 2 artigos ( [1] & [2] ) da documentação oficial da reação, implementei com ganchos, mas o valor parece não estar passando.

Eu coloquei uma demonstração simplificada no codesandbox [3] .

A implementação real é apenas mais algumas linhas (analisando e transformando em JSON).

Soluções alternativas que encontrei:

  • Se eu criar uma nova função em cada renderização em torno da função setValue , ela realmente funcionará.

    • mas isso vai contra o conselho de [1] sobre como evitar a criação de novos valores.

  • Migre-o para uma classe e use componentDidUpdate vez de useEffect .

    • Na verdade, estou usando isso agora, porque funciona. Incluindo salvar uma referência à função no estado.


Existe algo que não deveria funcionar no código abaixo? o efeito é acionado com as mudanças,
mas o valor não é atualizado nos componentes que consomem via gancho. veja o código de reprodução [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-passes-callbacks-down
[2] : https://reactjs.org/docs/context.html#updating -context-from-a-nested-component
[3] : https://codesandbox.io/s/0yzjr8vnrv


hlcecpq

Question

Comentários muito úteis

Eu coloquei uma demonstração simplificada no codesandbox [3].

Parece-me que suas useContext chamadas estão no mesmo componente que Provider . Nesse sentido, eles estão lendo o contexto acima do Provedor (o padrão).

O valor do provedor influencia apenas o contexto para os componentes dentro dele.

A propósito, se você não tentou enganar as regras do Hooks com código como [A, B].map(useContext) você deve ter percebido isso antes ;-)

Todos 3 comentários

Eu coloquei uma demonstração simplificada no codesandbox [3].

Parece-me que suas useContext chamadas estão no mesmo componente que Provider . Nesse sentido, eles estão lendo o contexto acima do Provedor (o padrão).

O valor do provedor influencia apenas o contexto para os componentes dentro dele.

A propósito, se você não tentou enganar as regras do Hooks com código como [A, B].map(useContext) você deve ter percebido isso antes ;-)

ei Dan! obrigado pela resposta rápida (: acabei de consertar para mim.

btw: useContext (via useStorage ) está dentro de App , que _está_ dentro de Provider na função ReactDOM.render . (talvez eu tenha tornado o exemplo muito curto para ver esse aninhamento).


solução :

Eu acabei de resolver modificando aquela linha peculiar .map : Eu perdi o parâmetro observedBits , que acabou sendo repassado Eu li sobre isso aqui nas edições / PRs, mas esqueci na hora de implementar, e acabou bagunçando o comportamento.

Aaah você está certo, eu interpretei mal o seu exemplo. Sim observedBits é o problema aqui. Parece uma armadilha, mas também não recomendamos chamar useContext dinamicamente.

Esta página foi útil?
0 / 5 - 0 avaliações