Eu sugiro que você dê uma olhada na resposta de Dan Abramov (um dos principais mantenedores do React) aqui :
Acho que você está tornando tudo mais complicado do que o necessário.
function Example() {
const [data, dataSet] = useState<any>(null)
useEffect(() => {
async function fetchMyAPI() {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}
fetchMyAPI()
}, [])
return <div>{JSON.stringify(data)}</div>
}
A longo prazo, desencorajaremos esse padrão porque incentiva as condições de corrida. Por exemplo, qualquer coisa pode acontecer entre o início e o fim da sua chamada e você pode ter obtido novos acessórios. Em vez disso, recomendaremos o Suspense para obtenção de dados, que se parecerá mais com
const response = MyAPIResource.read();
e sem efeitos. Mas enquanto isso, você pode mover o material assíncrono para uma função separada e chamá-lo.
Você pode ler mais sobre o suspense experimental aqui .
Se você quiser usar funções externas com o eslint.
function OutsideUsageExample() {
const [data, dataSet] = useState<any>(null)
const fetchMyAPI = useCallback(async () => {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}, [])
useEffect(() => {
fetchMyAPI()
}, [fetchMyAPI])
return (
<div>
<div>data: {JSON.stringify(data)}</div>
<div>
<button onClick={fetchMyAPI}>manual fetch</button>
</div>
</div>
)
}
Com useCallback useCallback . Sandbox .
import React, { useState, useEffect, useCallback } from "react";
export default function App() {
const [counter, setCounter] = useState(1);
// if counter is changed, than fn will be updated with new counter value
const fn = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
// if counter is changed, than fn will not be updated and counter will be always 1 inside fn
/*const fnBad = useCallback(() => {
setCounter(counter + 1);
}, []);*/
// if fn or counter is changed, than useEffect will rerun
useEffect(() => {
if (!(counter % 2)) return; // this will stop the loop if counter is not even
fn();
}, [fn, counter]);
// this will be infinite loop because fn is always changing with new counter value
/*useEffect(() => {
fn();
}, [fn]);*/
return (
<div>
<div>Counter is {counter}</div>
<button onClick={fn}>add +1 count</button>
</div>
);
}
useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, [])
eslint
me pede para fazerfetchMyAPI()
como dependência deuseEffect
Quando você usa uma função assíncrona como
ele retorna uma promessa e
useEffect
não espera que a função de retorno de chamada retorne Promise, em vez disso, espera que nada seja retornado ou que uma função seja retornada.Como uma solução alternativa para o aviso, você pode usar uma função assíncrona de chamada automática.
ou para torná-lo mais limpo, você pode definir uma função e chamá-la
a segunda solução tornará mais fácil de ler e ajudará você a escrever o código para cancelar as solicitações anteriores se uma nova for disparada ou salvar a última resposta da solicitação no estado
Códigosandbox de trabalho
fonte
useEffect
você pode retornar uma função para fazer a limpeza, como cancelar a assinatura de eventos. Quando você usa a função assíncrona você não pode retornar nada porqueuseEffect
não vai esperar o resultadoAté que o React forneça uma maneira melhor, você pode criar um auxiliar
useEffectAsync.js
:Agora você pode passar uma função assíncrona:
fonte
useAsyncEffect
que você escreveu pode facilmente enganar alguém e pensar que se eles retornassem uma função de limpeza de seu efeito assíncrono, ela seria executada no momento apropriado. Isso poderia levar a vazamentos de memória ou erros piores, então optamos por encorajar as pessoas a refatorar seu código para tornar a "costura" das funções assíncronas que interagem com o ciclo de vida do React mais visível, e o comportamento do código como resultado, esperançosamente, mais deliberado e correto.Eu li esta questão e sinto que a melhor maneira de implementar useEffect não é mencionada nas respostas. Digamos que você tenha uma chamada de rede e gostaria de fazer algo assim que obtivesse a resposta. Para simplificar, vamos armazenar a resposta da rede em uma variável de estado. Pode-se querer usar ação / redutor para atualizar a loja com a resposta da rede.
Referência => https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
fonte
experimentar
fonte
Para outros leitores, o erro pode vir do fato de que não há colchetes envolvendo a função assíncrona:
Considerando a função assíncrona initData
Este código levará ao seu erro:
Mas este não vai:
(Observe os colchetes em torno de initData ()
fonte
O operador void pode ser usado aqui.
Ao invés de:
ou
você poderia escrever:
É um pouco mais limpo e bonito.
Os efeitos assíncronos podem causar vazamentos de memória, por isso é importante realizar uma limpeza na desmontagem do componente. Em caso de busca, poderia ser assim:
fonte