Supongamos el siguiente ejemplo:
const example = () => { const [objects, setObjects] = useState([]) const asyncFunction = async() => { // This will trigger the API and assume it takes around 10 seconds to run let result = api.fetchObjects().then((result) => { // Here, setObjects will be called with the value it had at the moment the function started executing, not the actual value setObjects(result) } } }Mi pregunta es, ¿cuál es la mejor manera de hacer setObjects (resultado) y usar el estado actualizado? Digamos que el usuario puede agregar objetos a ese estado durante esos 10 segundos por diferentes medios en la aplicación.
Encontré una solución usando useEffect, así:
// Instead of setObjects(result) const [updateObjects, setUpdateObjects] = useState(null) setUpdateObjects(result) useEffect(() => { if (updateObjects !== null) { setObjects(updateObjects) setUpdateObjects(null) }Debe usar una actualización de estado funcional para acceder y actualizar desde el estado anterior.
Nota
A diferencia del método
setStateque se encuentra en los componentes de clase,useStateno fusiona automáticamente los objetos de actualización. Puede replicar este comportamiento combinando el formulario de actualización de funciones con la sintaxis de distribución de objetos:const [state, setState] = useState({}); setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; });
Uso de la cadena de promesas
const asyncFunction = () => { api.fetchObjects() .then((result) => { setObjects(objects => [ ...objects, // <-- shallow copy previous state array result, // <-- append new state ]); }); } o usando async/await
const asyncFunction = async () => { const result = await api.fetchObjects(); setObjects(objects => [ ...objects, // <-- shallow copy previous state array result, // <-- append new state ]); } Según la forma del estado real y el valor del result , la función de actualización del estado real puede verse un poco diferente según sus necesidades específicas.