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

React中Syncfusion DataGrid状态变更时模板列内容丢失问题

问题原因与解决方案

问题原因

你的Syncfusion DataGrid模板列在状态更新后内容丢失,核心原因是模板函数的引用变化:

  • 你将template函数定义在组件内部,每当counter状态更新触发组件重渲染时,都会生成一个全新的template函数实例。
  • Syncfusion React Grid在检测到template属性的引用发生变化后,无法正确重新渲染模板列,最终导致模板内容为空。

解决方案

方案1:用useMemo缓存模板函数

通过useMemo缓存模板函数,确保组件重渲染时template的引用保持一致:

import React, { useState, useMemo } from "react";
import {
  ColumnDirective,
  ColumnsDirective,
  GridComponent,
} from "@syncfusion/ej2-react-grids";
import "./App.css";
import { ExcelExport, Inject, Toolbar } from "@syncfusion/ej2-react-grids";

const DataGrid = (props) => {
  const data = [
    {
      OrderID: 10248,
      CustomerID: "VINET",
      EmployeeID: 5,
      OrderDate: new Date(8364186e5),
      ShipName: "Filiz Sarı Çelebi",
      ShipCity: "Reims",
      ShipAddress: "59 rue de l Abbaye",
      ShipRegion: "CJ",
      ShipPostalCode: "51100",
      ShipCountry: "France",
      Freight: 32.38,
      Verified: !0,
    },
    {
      OrderID: 10249,
      CustomerID: "TOMSP",
      EmployeeID: 6,
      OrderDate: new Date(836505e6),
      ShipName: "Emrah Çelebi",
      ShipCity: "İzmir",
      ShipAddress: "Luisenstr. 48",
      ShipRegion: "CJ",
      ShipPostalCode: "44087",
      ShipCountry: "Germany",
      Freight: 11.61,
      Verified: !1,
    },
    {
      OrderID: 10250,
      CustomerID: "HANAR",
      EmployeeID: 4,
      OrderDate: new Date(8367642e5),
      ShipName: "Hanari Carnes",
      ShipCity: "Rio de Janeiro",
      ShipAddress: "Rua do Paço, 67",
      ShipRegion: "RJ",
      ShipPostalCode: "05454-876",
      ShipCountry: "Brazil",
      Freight: 65.83,
      Verified: !0,
    },
  ];
  const [counter, setCounter] = useState(0);

  // 用useMemo缓存模板函数,空依赖数组确保只创建一次
  const template = useMemo(() => {
    return () => (
      <div>
        <input type="button" value="test" />
      </div>
    );
  }, []);

  return (
    <>
      <GridComponent id="grid" dataSource={data} height={150}>
        <Inject services={[Toolbar, ExcelExport]} />
        <ColumnsDirective>
          <ColumnDirective field="OrderID" width="100" textAlign="Right" />
          <ColumnDirective field="ShipCity" width="100" />
          <ColumnDirective field="EmployeeID" width="100" textAlign="Right" />
          <ColumnDirective
            field="Freight"
            width="100"
            format="C2"
            textAlign="Right"
          />
          <ColumnDirective field="ShipName" width="100" template={template} />
        </ColumnsDirective>
      </GridComponent>
      <div style={{ width: "100%", textAlign: "center" }}>
        Counter:{counter}
        <input
          type="button"
          onClick={() => setCounter(counter + 1)}
          value="+"
        />
      </div>
    </>
  );
};

export default DataGrid;

方案2:使用静态JSX元素作为模板

如果模板不需要依赖组件内的动态数据,直接定义为静态JSX元素即可,避免函数引用变化的问题:

// 直接定义静态模板元素
const template = <div><input type="button" value="test" /></div>;

// 在ColumnDirective中使用
<ColumnDirective field="ShipName" width="100" template={template} />

原理说明

  • useMemo会缓存函数实例,只有当依赖数组中的值变化时才会重新创建函数,确保template的引用在组件生命周期内稳定。
  • 静态JSX元素的引用不会随组件重渲染改变,Grid能始终正确识别并渲染模板内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:25:20