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

React从Firebase获取待办更新state,页面重载后state为空如何解决?

问题原因

Firebase Realtime Database 的 on('value') 是异步回调方法,你当前代码将 setState 写在了回调外部,执行顺序存在逻辑错误:

  1. 组件挂载时先声明空数组 data = []
  2. 注册 value 事件监听,此时不会立刻执行回调内的逻辑,需要等待网络请求返回数据
  3. 立刻使用当前空数组执行 setState,state 被赋值为空数组
  4. 后续拿到Firebase返回数据后,才会往已被赋值给state的数组中插入数据,但PureComponent依赖引用变化判断是否重渲染,数组引用没有变化的情况下不会触发重新渲染,因此页面始终显示为空。
    你在控制台看到的array(0)展开后有内容,是浏览器控制台打印引用类型的特性:打印时存储的是引用地址,你手动展开时数组已经被异步回调填充了数据,不代表执行setState时数组已经有值。

修复方案

调整代码逻辑如下:

  • 将setState移入value事件的回调函数内部,保证拿到Firebase返回数据后才更新state
  • 每次接收新数据时重新声明空数组组装数据,确保传递给setState的是新的数组引用,触发PureComponent重新渲染
  • 新增组件卸载时的监听移除逻辑,避免内存泄漏
  • 给列表渲染项添加key属性,符合React语法规范

完整修复代码

import React, { PureComponent } from 'react';
import firebase from 'firebase'

class Charts extends PureComponent {
    constructor(props) {
        super(props);
        this.state = { data: [] };
        this.todoRef = firebase.database().ref('Todo');
    }

    componentDidMount = () => {
        this.todoRef.on('value', (snapshot) => {
            const todos = snapshot.val();
            const data = [];
            for (let id in todos) {
                data.push({ id, ...todos[id] });
            }
            this.setState({ data: data })
        });
    }

    componentWillUnmount = () => {
        this.todoRef.off('value');
    }

    render() {
        return <div>
            {this.state.data.map(item => (
                <p key={item.id}>{item.name}</p>
            ))}
        </div>
    }
}

export default Charts;

内容的提问来源于stack exchange,提问作者Tomás Díaz Toro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:45:03