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

React结合Firebase实时数据库使用bootstrap-table时表格误报无匹配记录、搜索排序清空

问题根因
  • bootstrap-table 是基于 jQuery 的非 React 组件,初始化时会读取DOM初始状态生成内部维护的数据集,后续DOM的手动变更不会被插件感知
  • 现有代码中组件首次渲染时contactObjects为空对象,此时bootstrap-table已经完成初始化,内部记录的是空数据集
  • 后续Firebase返回数据、React重新渲染塞入的<tr>属于直接DOM操作,没有同步到bootstrap-table的内部状态,因此触发空数据集的“No matching records found”提示;触发搜索/排序时插件会按内部空数据集重绘DOM,覆盖掉手动塞入的内容,导致表格清空
解决方案

两种实现路径二选一即可:

方案1:数据加载完成后再手动初始化bootstrap-table(适配现有渲染逻辑)

  • 移除table标签上自动触发初始化的data-toggle="table"属性
  • 通过ref获取table的DOM节点
  • 监听数据状态变化,待数据加载完成后再执行插件初始化,同时先销毁历史实例避免重复初始化冲突
  • 为列表渲染的<tr>补充唯一key,消除React渲染警告
import React, { useState, useEffect, useRef } from "react";
import $ from "jquery";
import "bootstrap-table";
import firebaseDb from "../firebase";

const StarTrekTable = () => {
  const [contactObjects, setObjects] = useState({});
  const tableRef = useRef(null);

  useEffect(() => {
    firebaseDb.child("unwatched").on("value", (snapshot) => {
      if (snapshot.val() != null)
        setObjects({...snapshot.val()});
    });
  }, []);

  // 数据加载完成后初始化插件
  useEffect(() => {
    if (Object.keys(contactObjects).length > 0 && tableRef.current) {
      $(tableRef.current).bootstrapTable("destroy");
      $(tableRef.current).bootstrapTable({
        pagination: true,
        search: true
      });
    }
  }, [contactObjects]);

  return (
    <>
      <div className="jumbotron jumbotron-fluid">
        <div className="container">
          <h1 className="display-4 text-center">Star trek series</h1>
        </div>
      </div>
      <div>
        <div className="col-md-12">
          <table ref={tableRef}>
            <thead className="thread-light">
              <tr>
                <th>Title</th>
                <th>Series</th>
                <th>Season</th>
                <th>Episode</th>
                <th>Stardate</th>
                <th>Air Date</th>
              </tr>
            </thead>
            <tbody>
              {Object.keys(contactObjects).map((id) => {
                return (
                  <tr key={id}>
                    <td>{contactObjects[id].title}</td>
                    <td>{contactObjects[id].series}</td>
                    <td>{contactObjects[id].season}</td>
                    <td>{contactObjects[id].episode}</td>
                    <td>{contactObjects[id].stardate}</td>
                    <td>{contactObjects[id].airdate}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
};

export default StarTrekTable;

方案2:直接向插件传数据,完全适配bootstrap-table工作机制

这种方式不需要手动渲染tbody,插件会自行完成渲染,稳定性更高:

  • 将Firebase返回的对象数据转为数组格式存储
  • 移除手动渲染的tbody逻辑,通过table的data-data属性直接绑定数据源
  • 为每个th指定匹配的data-field,对应数据数组中的字段名
    核心代码片段:
// 状态中存储数组格式的表格数据
const [tableData, setTableData] = useState([]);

useEffect(() => {
  firebaseDb.child("unwatched").on("value", (snapshot) => {
    if (snapshot.val() != null) {
      // 将对象转为数组
      const dataArr = Object.values(snapshot.val());
      setTableData(dataArr);
    }
  });
}, []);

// table组件代码
<table
  ref={tableRef}
  data-pagination="true"
  data-search="true"
  data-data={tableData}
>
  <thead>
    <tr>
      <th data-field="title">Title</th>
      <th data-field="series">Series</th>
      <th data-field="season">Season</th>
      <th data-field="episode">Episode</th>
      <th data-field="stardate">Stardate</th>
      <th data-field="airdate">Air Date</th>
    </tr>
  </thead>
</table>
补充注意点
  • React代码中HTML的class属性必须替换为className,否则会触发控制台警告
  • 项目需正确引入Bootstrap、bootstrap-table、jQuery对应的CSS和JS依赖,确保插件功能正常
  • 数据更新时注意销毁旧的插件实例,避免多个实例共存导致的状态异常

内容的提问来源于stack exchange,提问作者First man on the sun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 07:24:10