簡體   English   中英

為什么我的代碼會創建一個新的空數組?

[英]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>
    </>
  )
}

解釋:

  1. onSubmit函數只需設置todos (無需進一步操作);
  2. todos發生變化時,將調用useEffect鈎子(只有此時您才 100% 確定todos將包含您必須存儲到 firebase 中的所有元素!);
  3. 現在在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM