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

React+TypeScript+MUI双DataGrid页面刷新后状态同步与持久化问题

双DataGrid双向联动与LocalStorage状态持久化解决方案

问题核心

  1. 两个DataGrid需双向同步选中状态:全量Grid选中的行进入收藏Grid,收藏Grid取消选中的行同步从全量Grid移除
  2. 页面刷新后状态丢失,且出现Warning: Cannot update a component (PeopleTables) while rendering a different component (ForwardRef(DataGrid))警告

关键修复点

1. 统一状态管理

用单一状态变量存储收藏行ID,作为两个DataGrid的状态源,避免多状态源导致的不一致。

2. 正确的LocalStorage同步逻辑

  • 组件初始化时从LocalStorage读取历史状态作为初始值
  • 用useEffect监听状态变化,异步写入LocalStorage,避免渲染阶段触发状态更新

3. 消除跨组件更新警告

所有状态更新必须放在事件回调或useEffect中,禁止在组件渲染过程中直接调用setState。

完整代码示例

import { useState, useEffect } from 'react';
import { DataGrid, GridRowSelectionModel } from '@mui/x-data-grid';

// 行数据类型定义
interface Person {
  id: number;
  name: string;
  // 可添加其他业务字段
}

// LocalStorage存储键名
const FAVORITE_STORAGE_KEY = 'favorite-person-ids';

const PeopleTables = () => {
  // 从LocalStorage加载初始收藏ID,默认空数组
  const initialFavorites = JSON.parse(
    localStorage.getItem(FAVORITE_STORAGE_KEY) || '[]'
  ) as GridRowSelectionModel;
  
  // 统一管理收藏ID状态
  const [favoriteIds, setFavoriteIds] = useState<GridRowSelectionModel>(initialFavorites);

  // 全量数据源示例
  const fullDataset: Person[] = [
    { id: 1, name: '张三' },
    { id: 2, name: '李四' },
    { id: 3, name: '王五' },
    { id: 4, name: '赵六' },
  ];

  // 动态生成收藏数据源:过滤全量数据中属于收藏的行
  const favoriteDataset = fullDataset.filter(person => favoriteIds.includes(person.id));

  // 状态变化时同步到LocalStorage
  useEffect(() => {
    localStorage.setItem(FAVORITE_STORAGE_KEY, JSON.stringify(favoriteIds));
  }, [favoriteIds]);

  // 处理全量Grid的选中事件:合并新选中的行到收藏列表
  const handleFullGridSelection = (newSelection: GridRowSelectionModel) => {
    // 去重合并,避免重复ID
    const updatedFavorites = [...new Set([...favoriteIds, ...newSelection])];
    setFavoriteIds(updatedFavorites);
  };

  // 处理收藏Grid的选中事件:移除取消选中的行
  const handleFavoriteGridSelection = (newSelection: GridRowSelectionModel) => {
    // 仅保留仍处于选中状态的ID
    const updatedFavorites = favoriteIds.filter(id => newSelection.includes(id));
    setFavoriteIds(updatedFavorites);
  };

  return (
    <div style={{ display: 'flex', gap: '24px', padding: '24px' }}>
      <div style={{ width: 500 }}>
        <h3>全量数据列表</h3>
        <DataGrid
          rows={fullDataset}
          columns={[
            { field: 'id', headerName: 'ID', width: 70 },
            { field: 'name', headerName: '姓名', flex: 1 },
          ]}
          checkboxSelection
          rowSelectionModel={favoriteIds}
          onRowSelectionModelChange={handleFullGridSelection}
        />
      </div>
      <div style={{ width: 500 }}>
        <h3>收藏列表</h3>
        <DataGrid
          rows={favoriteDataset}
          columns={[
            { field: 'id', headerName: 'ID', width: 70 },
            { field: 'name', headerName: '姓名', flex: 1 },
          ]}
          checkboxSelection
          // 仅同步当前收藏数据中存在的ID,避免无效选中
          rowSelectionModel={favoriteIds.filter(id => favoriteDataset.some(p => p.id === id))}
          onRowSelectionModelChange={handleFavoriteGridSelection}
        />
      </div>
    </div>
  );
};

export default PeopleTables;

代码说明

  • 单一状态源:favoriteIds同时控制两个Grid的选中状态,确保双向同步一致
  • LocalStorage同步:通过useEffect异步写入,避免渲染阶段的状态更新冲突
  • 收藏Grid选中过滤:只同步当前收藏数据中存在的ID,防止出现无效选中状态
  • 事件驱动更新:所有状态更新都由用户选中事件触发,消除跨组件渲染更新的警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:53:14