Yassine Layachi
Me gustaría llamar a una función asíncrona y obtener el resultado de mi UseEffect.
Los ejemplos de fetch api que encontré en Internet se realizan directamente en la función useEffect. Si mi URL cambia, debo parchear todas mis búsquedas.
Cuando lo intenté, recibí un mensaje de error.
Este es mi código.
async function getData(userId) {
const data = await axios.get(`http://url/api/data/${userId}`)
.then(promise => {
return promise.data;
})
.catch(e => {
console.error(e);
})
return data;
}
function blabla() {
const [data, setData] = useState(null);
useEffect(async () => {
setData(getData(1))
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
index.js:1375 Advertencia: una función de efecto no debe devolver nada más que una función, que se usa para la limpieza. Parece que escribiste useEffect(async () => …) o devolviste una Promesa. En su lugar, escribe la función asíncrona dentro de tu efecto y llámala inmediatamente:
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
Fracción
Cree una función asíncrona dentro de su efecto que espere el getData(1)
resultado luego llamar setData()
:
useEffect(() => {
const fetchData = async () => {
const data = await getData(1);
setData(data);
}
fetchData();
}, []);
-
¿Por qué esto es diferente a si la función asíncrona se definiera fuera del enlace useEffect?
–Leland Reardon
17 de agosto de 2021 a las 15:43
-
@LelandReardon Si desea definir la función asíncrona fuera de la
useEffect
gancho, tienes que agregarlo a la lista de dependencias deuseEffect
y envolver su definición en unuseCallback
con las dependencias necesarias para evitar llamadas innecesarias, para obtener más información, consulte la documentación de reacción aquí– Fracción
24 de agosto de 2021 a las 11:34
Si lo está invocando de inmediato, es posible que desee usarlo como una función anónima:
useEffect(() => {
(async () => {
const data = await getData(1);
setData(data);
})();
}, []);
-
¿Cuales son los beneficios?
– Remi
6 de octubre de 2020 a las 11:58
-
@Remi La función se invocará de inmediato y no se usará en ningún otro lugar, por lo que no necesita un nombre ni ninguna predefinición
– hsusanoo
6 oct 2020 a las 12:10
-
¿Qué hay de cancelar la solicitud si el componente se desmonta?
– Remi
6 oct 2020 a las 12:15
-
@Remi esto no está relacionado con la pregunta de OP, puede hacer esta pregunta en un hilo separado, ya que puede tener diferentes implementaciones, la mayoría de las cuales no están relacionadas con si usa un asíncrono anónimo o uno predefinido para obtener datos
– hsusanoo
6 de octubre de 2020 a las 12:23
-
Caso extremo. Si no lo está cancelando, React establecerá un estado incluso cuando este componente esté desmontado. Creo que algunas bibliotecas de prueba incluso se quejarán. Por lo tanto este ejemplo no es recomendable persé.
– Remi
6 oct 2020 a las 14:45
zilijonas
Sería mejor si hiciera lo que sugiere la advertencia: llame a la función asíncrona dentro del efecto.
function blabla() {
const [data, setData] = useState(null);
useEffect(() => {
axios.get(`http://url/api/data/1`)
.then(result => {
setData(result.data);
})
.catch(console.error)
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
Si desea mantener la función api fuera del componente, también puede hacer esto:
async function getData(userId) {
const data = await axios.get(`http://url/api/data/${userId}`)
.then(promise => {
return promise.data;
})
.catch(e => {
console.error(e);
})
return data;
}
function blabla() {
const [data, setData] = useState(null);
useEffect(() => {
(async () => {
const newData = await getData(1);
setData(newData);
})();
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
-
Gracias por la respuesta. Desafortunadamente, esto es exactamente lo que no quiero hacer. Si mi URL cambia, debo parchearla en todos los archivos que busqué. Para la escalabilidad, estoy tratando de hacer algo más como el primer código que publiqué.
– Yassine Layachi
1 julio 2019 a las 16:00
-
Podrías usar variables de entorno
– Monstar
22 de marzo de 2022 a las 21:28
Ying Yang
Desde getData
devuelve una Promesa, podrías simplemente usar .then
. En su caso, esto es mucho más simple que escribir una función asíncrona y llamarla directamente.
Además, desde axios.get
ya devuelve una Promesa, tu getData
la función no necesita ser marcada async
. Esta es una versión simplificada y funcional de su código:
function getData(userId) {
return axios.get(`http://url/api/data/${userId}`)
.then(promise => promise.data)
.catch(e => {
console.error(e);
});
}
function blabla() {
const [data, setData] = useState(null);
useEffect(async () => {
getData(1).then(setData);
}, []);
return (
<div>
this is the {data["name"]}
</div>
);
}
brunettdan
El componente puede desmontarse o volver a renderizarse con diferentes someId
antes de que se resuelva await:
const unmountedRef = useRef(false);
useEffect(()=>()=>(unmountedRef.current = true), []);
useEffect(() => {
const effectStale = false; // Don't forget ; on the line before self-invoking functions
(async function() {
// You can await here
const response = await MyAPI.getData(someId);
/* Component has been unmounted. Stop to avoid
"Warning: Can't perform a React state update on an unmounted component." */
if(unmountedRef.current) return;
/* Component has re-rendered with different someId value
Stop to avoid updating state with stale response */
if(effectStale) return;
// ... update component state
})();
return ()=>(effectStale = true);
}, [someId]);
Considere usar Suspenso para los datos que deben cargarse antes de montar el componente.
jamesk
Todavía puede definir la función asíncrona fuera del gancho y llamarla dentro del gancho.
const fetchData = async () => {
const data = await getData(1);
setData(data);
}
useEffect(() => {
fetchData();
}, []);
Si una función devuelve una promesa, puede
await
o.then(...)
no ambos.– Omagario
1 de julio de 2019 a las 15:36
Supongo que esto responde la pregunta, pero de ninguna manera esto realmente resuelve el problema. Efectivamente, está comenzando una promesa que podría terminar en cualquier momento. Si su trabajo asíncrono no está relacionado con el ciclo de vida de los componentes, está bien. Pero de lo contrario, se encontrará con problemas y errores de representación difíciles de depurar. No tengo suficiente experiencia con React para estar seguro, pero siento que esto también interfiere con el sistema de dependencia de React.
– Romain Vicente
20 de abril de 2021 a las 8:44
Consulte también las advertencias de React Hook para la función asíncrona en useEffect
– Bergi
11 de noviembre de 2021 a las 19:32