Este es mi código:
const Practice = () => { const [todo, setTodo] =useState(""); const [todos,setTodos]=useState([]) const onSubmit =async(event) =>{ event.preventDefault(); setTodos((currnet)=>[todo, ...currnet]) setTodo("") try { const docRef = await addDoc(collection(db, "todos"), { todos, }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } } const onChange = (event)=>{ setTodo(event.target.value) } console.log(todos) return ( <> <form onSubmit={onSubmit}> <input onChange={onChange} value={todo} type="text" placeholder="Write" /> <input type="submit" value="GO!!" /> </form> </> ) }e ingresé algunas palabras en la etiqueta, pero la última palabra ingresada no existe en mi base de datos de firebase. ¿Por qué no existe mi base de datos? y ¿por qué crear una nueva matriz vacía? ingrese la descripción de la imagen aquí
Su problema está relacionado con la naturaleza asíncrona de los ganchos.
En la función onSubmit , está configurando todos usando el gancho setTodos (que es asíncrono) y luego está leyendo el valor de todos (para almacenarlo en firebase).
¡No puedes escribir este código en un contexto asíncrono! De hecho, podría ser que todos se lean antes de que el gancho lo establezca (y el resultado será que no todos los datos se almacenarán en firebase).
Para resolver este error, debe usar useEffect hook de esta manera:
const Practice = () => { const [todo, setTodo] =useState(""); const [todos,setTodos]=useState([]) useEffect(() => { // 1) define an async function in useEffect hook const storeData = async () => { try { const docRef = await addDoc(collection(db, "todos"), { todos, }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } } // 2) reset todo setTodo(""); // 3) store todos into firebase storeData(); }, [todos]); const onSubmit =async(event) =>{ event.preventDefault(); setTodos((currnet)=>[todo, ...currnet]); } const onChange = (event)=>{ setTodo(event.target.value) } return ( <> <form onSubmit={onSubmit}> <input onChange={onChange} value={todo} type="text" placeholder="Write" /> <input type="submit" value="GO!!" /> </form> </> ) }Explicación:
onSubmit solo necesita configurar todos (no se requieren más acciones);todos cambie, se llamará a useEffect hook (¡solo que en este momento está 100% seguro de que todos contendrá todos los elementos que tiene que almacenar en firebase!);useEffect , puede limpiar todo y luego llamar a la función storeData para almacenar todo en todos . Nota adicional: por qué definí una función asíncrona en useEffect si pudiera escribir algo como:
useEffect(async () => { // never use async useEffect!!! try { const docRef = await addDoc(collection(db, "todos"), { todos, }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); } }, [todos]) Hay una razón por la que no puedes escribir useEffect asíncrono, pero no soy un experto, así que te sugiero que leas este artículo.