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
相关产品推荐
相关产品推荐

