[英]Why does my code create a new empty array?
這是我的代碼:
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>
</>
)
}
我在標簽中輸入了一些單詞,但最后一個輸入單詞不存在我的 firebase 數據庫。 為什么不存在我的數據庫? 為什么要創建新的空數組? 在此處輸入圖像描述
您的問題與鈎子的異步性質有關。
在onSubmit
函數中,您正在使用setTodos
鈎子(即異步)設置todos
,然后您正在讀取todos
值(將其存儲到 firebase 中)。
您不能在異步上下文中編寫此代碼! 事實上,可能是在鈎子設置他之前會讀取todos
(結果將是並非所有數據都將存儲到 firebase 中)。
要解決此錯誤,您必須以這種方式使用useEffect
鈎子:
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>
</>
)
}
解釋:
onSubmit
函數只需設置todos
(無需進一步操作);todos
發生變化時,將調用useEffect
鈎子(只有此時您才 100% 確定todos
將包含您必須存儲到 firebase 中的所有元素!);useEffect
中,您可以清理todo
,然后調用storeData
函數將待辦事項存儲到todos
中。 附加說明:為什么我在useEffect
中定義了一個異步函數,如果我可以編寫如下內容:
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])
你不能寫異步useEffect
是有原因的,但我不是專家,所以我強烈建議你閱讀這篇文章。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.