繁体   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