You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React从Firebase读取数据返回空数组,如何解决?

问题:Todo CRUD应用无法正确渲染数据

我正在开发一个简易的Todo CRUD应用,无法将数据渲染到页面上。目前console.log(doc.data())能正常显示所有数据集,但todos数组仅能获取首个值或返回空数组,求解决思路。

const Home = () => {

  const [todos,setTodos] = useState([]);

  const getTodos = async () =>{
    const querySnapshot = await getDocs(collection(db, "todos"));
    
    querySnapshot.forEach((doc) => {        
      setTodos([...todos,doc.data()])
      console.log(doc.data())
      console.log(todos)
    });  
  }

  useEffect(()=>{  
    getTodos();    
  },[])

  return (    
    <div>Home</div>
  )
}

问题原因

循环调用setTodos([...todos, doc.data()])时,todos始终是初始的空数组——因为React状态更新是异步的,循环里的每一次setTodos都捕获了初始的todos值,最终只会保留最后一次添加的数据,或因异步时序问题仅显示第一条。

解决思路

  1. 一次性收集数据后更新状态
    先把所有todo数据存入临时数组,再一次性调用setTodos,避免多次异步更新的冲突:

    const getTodos = async () =>{
      const querySnapshot = await getDocs(collection(db, "todos"));
      const newTodos = querySnapshot.docs.map(doc => doc.data());
      setTodos(newTodos);
    }
    
  2. 用函数式更新确保状态最新
    如果需要逐步更新状态,改用setTodos的函数式写法,每次更新都基于上一次的最新状态:

    querySnapshot.forEach((doc) => {        
      setTodos(prevTodos => [...prevTodos, doc.data()]);
    });
    
  3. 补充页面渲染逻辑
    最后要在组件的返回值里渲染todos数据,比如:

    return (    
      <div>
        <h2>我的待办</h2>
        {todos.map((todo, idx) => (
          <div key={idx} className="todo-item">
            {todo.title} {/* 替换成你的todo实际字段名 */}
          </div>
        ))}
      </div>
    )
    

内容的提问来源于stack exchange,提问作者jungs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:09:54