MUI DataGrid中React状态更新后对应列未更新问题求助
解决Material-UI DataGrid列不随状态更新的问题
问题根源
- 状态类型不一致:你初始化
brandMap用的是new Map(),但更新时却转换成了普通对象({ ...prevState, ...data.data.reduce(...) }),这会导致后续brandMap[params.value]的访问逻辑异常,类型突变也可能干扰React的状态更新检测。 - Columns未监听
brandMap变化:你仅在user变化时通过useEffect生成并设置columns,当brandMap更新后,columns不会重新生成,renderCell里的brandMap还是闭包中保存的旧值,自然无法同步更新显示。
修复步骤
步骤1:统一状态类型
把brandMap统一为普通对象(更适配你的访问方式),初始化时用空对象:
const [brandMap, setBrandMap] = useState({});
步骤2:让Columns响应brandMap变化
不在useEffect里生成columns,直接在组件主体中定义,让它依赖brandMap。这样每次brandMap更新,columns都会重新创建,DataGrid就能拿到最新的渲染逻辑:
// 直接在组件内定义columns,而非useEffect中 const columns = [ { field: 'image', headerName: '', filterable: false, renderCell: (params) => ( <img src={params.value} style={{width: "100px", height: "100px"}}/> ) }, { field: 'name', headerName: 'Name', editable: true, filterOperators, flex: 1 }, { field: 'sku', headerName: 'SKU', editable: true, filterOperators, flex: 1 }, // ...其他列 { field: 'brand_id', headerName: 'Brand', editable: true, flex: 1, renderCell: (params) => ( <Typography variant="body2" color="text.secondary" component="p" style={{color: 'purple'}} > {brandMap[params.value] ?? <CircularProgress size={20} />} </Typography> ) }, // ...其他列 ]; // 原useEffect仅负责数据初始化 useEffect(() => { updateData(1); fetchBrands(); }, [user]);
步骤3:优化fetchBrands的状态更新逻辑
去掉await和then混合写法,保持代码简洁清晰:
async function fetchBrands() { const accessToken = await getToken(); const response = await fetch("http://localhost:8000/auth/brands", { method: "GET", headers: { Authorization: `Bearer ${accessToken}` } }); const data = await response.json(); const newBrandMap = data.data.reduce((map, obj) => { map[obj.id] = obj.name; return map; }, {}); // 合并新旧状态 setBrandMap(prev => ({ ...prev, ...newBrandMap })); }
额外说明
如果坚持使用Map类型,需调整访问和更新逻辑:
// 初始化 const [brandMap, setBrandMap] = useState(new Map()); // 更新逻辑 setBrandMap(prev => { const newMap = new Map(prev); data.data.forEach(obj => newMap.set(obj.id, obj.name)); return newMap; }); // renderCell中访问 {brandMap.get(params.value) ?? <CircularProgress size={20} />}
这种情况下同样要让columns依赖brandMap,确保状态更新时列的渲染逻辑同步更新。
内容的提问来源于stack exchange,提问作者Oze
相关产品推荐
相关产品推荐

