React使用material-table编辑行打开上传弹窗后编辑状态退出问题
问题原因
你遇到的编辑状态自动退出问题是重渲染导致的,具体触发逻辑如下:
- 点击上传按钮时调用
setOpen(true)修改了组件状态,触发App根组件重渲染 - 你当前把
columns配置直接写在MaterialTable的props里,每次组件重渲染都会生成全新的columns数组引用 - material-table内部检测到columns配置变更,就会自动终止当前行的编辑状态,清空未保存的修改
新增行时你没有感知到问题,是因为触发弹窗时你还没在新增行输入内容,就算编辑状态退出也不会有明显的内容丢失,所以误以为只有编辑行有问题。
修复方案
做两处修改即可解决:
1. 缓存columns配置
把columns定义移到组件外部,或者使用useMemo缓存columns的引用,避免重渲染时生成新引用:
如果columns没有依赖组件内部状态,优先直接移到App组件外:
const TABLE_COLUMNS = [ { field: "url", title: "Url", editComponent: () => ( <Button variant="contained" color="primary" onClick={() => setOpen(true)} > Add image </Button> ), render: (rowData) => <img src={rowData.url} /> }, { field: "name", title: "Name" } ] const App = () => { // 原有组件逻辑不变 return ( <Container maxWidth={"xl"}> <MaterialTable columns={TABLE_COLUMNS} {/* 其他原有props保持不变 */} /> {/* 原有弹窗逻辑不变 */} </Container> ) }
如果columns依赖组件内部的状态/方法,就用useMemo缓存:
import React, { useState, useMemo } from "react"; const App = () => { const [open, setOpen] = useState(false); // 其他原有状态声明不变 const columns = useMemo(() => [ { field: "url", title: "Url", editComponent: () => ( <Button variant="contained" color="primary" onClick={() => setOpen(true)} > Add image </Button> ), render: (rowData) => <img src={rowData.url} /> }, { field: "name", title: "Name" } ], [setOpen]) // 把依赖的变量放入依赖数组 return ( <Container maxWidth={"xl"}> <MaterialTable columns={columns} {/* 其他原有props保持不变 */} /> {/* 原有弹窗逻辑不变 */} </Container> ) }
2. 可选优化:缓存其他固定配置
同理,pageSize、editable这些不需要随组件状态变化的配置,也可以移到组件外或者用useMemo缓存,避免不必要的重渲染检测。
内容的提问来源于stack exchange,提问作者tommi
相关产品推荐
相关产品推荐

