Com o React 16.8.6 (foi bom na versão anterior 16.8.3), recebo esse erro ao tentar impedir um loop infinito em uma solicitação de busca
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
Não consegui encontrar uma solução que interrompa o loop infinito. Eu quero ficar longe de usar useReducer()
. Eu encontrei essa discussão em https://github.com/facebook/react/issues/14920, onde uma possível solução é You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.
não estar confiante no que estou fazendo, por isso ainda não tentei implementá-la.
Eu tenho essa configuração atual React hook useEffect é executado continuamente para sempre / loop infinito e o único comentário é sobre o useCallback()
qual eu não estou familiarizado.
Como estou usando no momento useEffect()
(que só quero executar uma vez no começo, semelhante a componentDidMount()
)
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
useCallback()
. Assim, por exemplo:const fetchBusinesses= useCallback(() => { ... }, [...])
euseEffect()
ficaria assim:useEffect(() => { fetchBusinesses(); }, [fetchBusinesses]);
// eslint-disable-next-line react-hooks/exhaustive-deps
para explicar ao linter que seu código está correto é como um hack. Espero que eles vão encontrar uma outra solução para tornar o linter mais inteligente o suficiente para detectar quando um argumento não é obrigatórioNão é erro de JS / React, mas aviso de eslint (eslint-plugin-react-hooks).
Ele está lhe dizendo que o gancho depende da função
fetchBusinesses
, então você deve passá-lo como dependência.Isso poderia resultar na chamada da função a cada renderização se a função for declarada no componente como:
porque toda vez que a função é redeclarada com nova referência
A maneira correta de fazer isso é:
ou apenas definindo função em
useEffect
Mais: https://github.com/facebook/react/issues/14920
fonte
Line 20: The 'fetchBusinesses' function makes the dependencies of useEffect Hook (at line 51) change on every render. Move it inside the useEffect callback. Alternatively, wrap the 'fetchBusinesses' definition into its own useCallback() Hook
Você pode configurá-lo diretamente como
useEffect
retorno de chamada:Ele será acionado apenas uma vez, portanto, verifique se todas as dependências da função estão definidas corretamente (o mesmo que usar
componentDidMount/componentWillMount...
)Editar 21/02/2020
Apenas para completar:
1. Use a função como
useEffect
retorno de chamada (como acima)2. Declare a função para dentro
useEffect()
3. Memorize com
useCallback()
Nesse caso, se você tiver dependências em sua função, precisará incluí-las na
useCallback
matriz de dependências e isso será acionadouseEffect
novamente se os parâmetros da função mudarem. Além disso, é um monte de clichê ... Então, basta passar a função diretamente parauseEffect
como em1. useEffect(fetchBusinesses, [])
.4. Desative o aviso de eslint
fonte
A solução também é dada pelo
useCallback
react , eles recomendam que você retorne uma versão memoize da sua função:useCallback
é simples de usar, pois tem a mesma assinatura queuseEffect
a diferença é que useCallback retorna uma função. Seria assim:fonte
Esses avisos são muito úteis para encontrar componentes que não são atualizados consistentemente: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of- dependências .
No entanto, se você deseja remover os avisos em todo o seu projeto, você pode adicioná-lo à sua configuração de eslint:
fonte
Este artigo é um bom manual para obter dados com ganchos: https://www.robinwieruch.de/react-hooks-fetch-data/
Essencialmente, inclua a definição da função de busca dentro
useEffect
:fonte
Você pode remover a segunda matriz do tipo de argumento,
[]
masfetchBusinesses()
ela também será chamada a cada atualização. Você pode adicionar umaIF
declaração àfetchBusinesses()
implementação, se quiser.O outro é implementar a
fetchBusinesses()
função fora do seu componente. Apenas não esqueça de passar argumentos de dependência para suafetchBusinesses(dependency)
ligação, se houver.fonte
Na verdade, os avisos são muito úteis quando você desenvolve com ganchos. mas, em alguns casos, pode agulhá-lo. especialmente quando você não precisa escutar alterações nas dependências.
Se você não deseja colocar
fetchBusinesses
dentro das dependências do gancho, basta passá-lo como argumento para o retorno de chamada do gancho e definir o principalfetchBusinesses
como o valor padrão para este tipo de ação.Não é uma prática recomendada, mas pode ser útil em alguns casos.
Também como Shubnam escreveu, você pode adicionar o código abaixo para dizer ao ESLint para ignorar a verificação do seu gancho.
fonte
Você pode retirar
fetchBusinesses
completamente do seu componente:Isso não apenas fornecerá uma solução simples e resolverá o aviso de esgotamentos.
fetchBusiness
agora pode ser testado melhor e facilitaComp
, pois reside no escopo do módulo fora da árvore do React.A realocação
fetchBusinesses
externa funciona bem aqui, pois só poderíamos ler adereços e estados iniciais do componente de qualquer maneira devido ao escopo de fechamento obsoleto ([]
dep inuseEffect
).Como omitir dependências de função
useEffect
depender desse valor (função de computação pura)useCallback
como último recursoEm relação a outras soluções:
Puxando para
fetchBusinesses
dentrouseEffect()
realmente não ajuda, se você acessar outro estado nele. O eslint ainda reclamaria: Codesandbox .Eu também evitaria os deps exaustivos que ignoram os comentários. É fácil esquecê-los quando você faz alguma refatoração e revisão de suas dependências.
fonte
Esta é uma solução bastante simples e você não precisa substituir os avisos es-lint. Basta manter um sinalizador para verificar se o componente está montado ou não.
fonte
você tenta assim
e
é trabalho para você. Mas a minha sugestão é tentar desta forma também trabalhar para você. É melhor do que antes. Eu uso desta maneira:
se você obtiver dados com base na identificação específica, adicione o uso de retorno de chamada useEffect
[id]
, não será possível exibir avisoReact Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array
fonte
basta desativar o eslint para a próxima linha;
dessa maneira, você o está usando exatamente como um componente foi montado (chamado uma vez)
Atualizada
ou
fetchBusinesses será chamado sempre que someDeps mudar
fonte
[fetchBusinesses]
removerá automaticamente o aviso e isso resolveu o problema para mim.useEffect
verificar se o estado está vazio.