material-table 在编辑行中打开对话框关闭行编辑后
material-table after open dialog in edit row is closed edit of row
我在 Reactjs 库中使用 material-table。我有一个用于使用对话框添加图像的列按钮。它适用于添加新行,但如果我想在打开对话框 关闭行编辑后编辑行 。我认为这个问题可能是由重新渲染引起的。
打开编辑行
单击按钮后打开了添加图像的对话框,但行的编辑已结束,我无法保存更改。
import { Button, Container, IconButton } from "@material-ui/core";
import MaterialTable from "@material-table/core";
import React, { useState } from "react";
import { DropzoneDialogBase } from "material-ui-dropzone";
import CloseIcon from "@material-ui/icons/Close";
import { tableIcons } from "./IconProvider";
const App = () => {
const [equipment, setEquipment] = useState([{url: '', name: 'Test'}]);
const [open, setOpen] = useState(false);
const [image, setImage] = useState([]);
const FILES_LIMIT = 1;
const pageSize = [10, 20, 50, 100];
const dialogTitle = () => (
<>
<span>Upload file</span>
<IconButton
style={{ right: "12px", top: "8px", position: "absolute" }}
onClick={() => setOpen(false)}
>
<CloseIcon />
</IconButton>
</>
);
return (
<Container maxWidth={"xl"}>
<MaterialTable
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" }
]}
data={equipment}
title={"Title"}
options={{
pageSizeOptions: pageSize,
pageSize: pageSize[0]
}}
icons={tableIcons}
editable={{
onRowAdd: (newData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
setEquipment([...equipment, newData]);
resolve();
}, 1000);
}),
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
const dataUpdate = [...equipment];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
setEquipment([...dataUpdate]);
resolve();
}, 1000);
}),
onRowDelete: (oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
const dataDelete = [...equipment];
const index = oldData.tableData.id;
dataDelete.splice(index, 1);
setEquipment([...dataDelete]);
resolve();
}, 1000);
})
}}
/>
<DropzoneDialogBase
dialogTitle={dialogTitle()}
acceptedFiles={["image/*"]}
fileObjects={image}
cancelButtonText={"cancel"}
submitButtonText={"submit"}
maxFileSize={5000000}
filesLimit={FILES_LIMIT}
open={open}
onAdd={(newFileObjs) => {
setImage([].concat([], newFileObjs));
}}
onDelete={(deleteFileObj) => {
setImage(image.filter((item) => item !== deleteFileObj));
}}
onClose={() => setOpen(false)}
onSave={() => {
setOpen(false);
}}
showPreviews={true}
showFileNamesInPreview={true}
/>
</Container>
);
};
export default App;
我在 Codesandbox
创建了考试
你是对的,问题发生是因为你在每次状态更新时触发重新渲染,当提供给 material table 的列是静态的,但包含在每次渲染时更新的函数时,就会发生这种情况,重置 table 状态。提供 stable 函数或列引用或行 ID 以防止状态丢失。
所以,你修复的是:
const preventRerender = useCallback((rowData) => <img src={rowData.url} />, []);
const editComponent = useCallback(() => {
return <Button
variant="contained"
color="primary"
onClick={() => setOpen(true)}
>
{"Add image"}
</Button>;
}, [])
<MaterialTable
columns={[
{
field: "url",
title: "Url",
editComponent,
render: preventRerender
},
{ field: "name", title: "Name" }
]}
通过添加回调或 useMemo,如果你想通过更新数组依赖,你将阻止更新状态。
补充说明,跟踪并注意行 key/id
我在 Reactjs 库中使用 material-table。我有一个用于使用对话框添加图像的列按钮。它适用于添加新行,但如果我想在打开对话框 关闭行编辑后编辑行 。我认为这个问题可能是由重新渲染引起的。
打开编辑行
单击按钮后打开了添加图像的对话框,但行的编辑已结束,我无法保存更改。
import { Button, Container, IconButton } from "@material-ui/core";
import MaterialTable from "@material-table/core";
import React, { useState } from "react";
import { DropzoneDialogBase } from "material-ui-dropzone";
import CloseIcon from "@material-ui/icons/Close";
import { tableIcons } from "./IconProvider";
const App = () => {
const [equipment, setEquipment] = useState([{url: '', name: 'Test'}]);
const [open, setOpen] = useState(false);
const [image, setImage] = useState([]);
const FILES_LIMIT = 1;
const pageSize = [10, 20, 50, 100];
const dialogTitle = () => (
<>
<span>Upload file</span>
<IconButton
style={{ right: "12px", top: "8px", position: "absolute" }}
onClick={() => setOpen(false)}
>
<CloseIcon />
</IconButton>
</>
);
return (
<Container maxWidth={"xl"}>
<MaterialTable
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" }
]}
data={equipment}
title={"Title"}
options={{
pageSizeOptions: pageSize,
pageSize: pageSize[0]
}}
icons={tableIcons}
editable={{
onRowAdd: (newData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
setEquipment([...equipment, newData]);
resolve();
}, 1000);
}),
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
const dataUpdate = [...equipment];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
setEquipment([...dataUpdate]);
resolve();
}, 1000);
}),
onRowDelete: (oldData) =>
new Promise((resolve, reject) => {
setTimeout(() => {
const dataDelete = [...equipment];
const index = oldData.tableData.id;
dataDelete.splice(index, 1);
setEquipment([...dataDelete]);
resolve();
}, 1000);
})
}}
/>
<DropzoneDialogBase
dialogTitle={dialogTitle()}
acceptedFiles={["image/*"]}
fileObjects={image}
cancelButtonText={"cancel"}
submitButtonText={"submit"}
maxFileSize={5000000}
filesLimit={FILES_LIMIT}
open={open}
onAdd={(newFileObjs) => {
setImage([].concat([], newFileObjs));
}}
onDelete={(deleteFileObj) => {
setImage(image.filter((item) => item !== deleteFileObj));
}}
onClose={() => setOpen(false)}
onSave={() => {
setOpen(false);
}}
showPreviews={true}
showFileNamesInPreview={true}
/>
</Container>
);
};
export default App;
我在 Codesandbox
创建了考试你是对的,问题发生是因为你在每次状态更新时触发重新渲染,当提供给 material table 的列是静态的,但包含在每次渲染时更新的函数时,就会发生这种情况,重置 table 状态。提供 stable 函数或列引用或行 ID 以防止状态丢失。
所以,你修复的是:
const preventRerender = useCallback((rowData) => <img src={rowData.url} />, []);
const editComponent = useCallback(() => {
return <Button
variant="contained"
color="primary"
onClick={() => setOpen(true)}
>
{"Add image"}
</Button>;
}, [])
<MaterialTable
columns={[
{
field: "url",
title: "Url",
editComponent,
render: preventRerender
},
{ field: "name", title: "Name" }
]}
通过添加回调或 useMemo,如果你想通过更新数组依赖,你将阻止更新状态。
补充说明,跟踪并注意行 key/id