单击操作时以动态方式加载列表中每个项目的材质 UI 对话框的正确方法是什么?

Hos*_*lah 1 reactjs material-ui

假设我有一个客户列表,并以表格格式显示它们。

我可以在每个客户行的末尾添加一些图标,以让用户管理每一行。典型的图标是删除编辑之类的图标。

现在我想添加一个图标/操作,它打开一个对话框,将一些数据从行传递到对话框,并在对话框关闭时从对话框获取数据。

在 Angular 中,我会很容易地做到这一点。因为我可以以编程方式调用一个showDialog方法或类似的方法,并将参数传递给它,并获取结果。它非常有活力。

然而,在 React + Material UI 中,我陷入了困境。

我想渲染一个对话框,并在单击每一行的操作时,我想显示该对话框并将数据传递给它,并从中获取数据。

正确的做法是什么?

Mhd*_*osh 5

使用视图或编辑对话框呈现数据列表,可以使用 React 和 MUI 处理每个项目

最低要求是:

  1. 创建一个对话框组件,该组件可以:显示信息、编辑信息并点击保存
  2. 一个父组件,它呈现所有数据并具有对话框的打开/关闭逻辑,并且可以以您喜欢的方式连接到 API

这是一个用 React、mui 和 typescript 制作的示例

定义样本数据和类型


const tablesData = [
    { customerId: 1, customerName: 'customer1', address: 'some address 1' },
    { customerId: 2, customerName: 'customer2', address: 'some address 2' },
    { customerId: 3, customerName: 'customer3', address: 'some address 3' },
    { customerId: 4, customerName: 'customer4', address: 'some address 4' },
    { customerId: 5, customerName: 'customer5', address: 'some address 5' },
];

type Customer = typeof tablesData[number];


Run Code Online (Sandbox Code Playgroud)

定义了一个对话框组件,可以显示客户的地址,如果需要,可以编辑该地址并稍后提交给 API

interface EditCustomerDialogProps {
    open: boolean,
    closeHandler: () => void,
    customer: Customer,
    onSave: (customer: Customer) => void,
}

function EditCustomerDialog(props: EditCustomerDialogProps) {

    const { open, closeHandler, customer, onSave } = props;

    useEffect(function onCustomerChangeUpdateFormValues() {
        setAddress(customer.address);
    }, [customer]);

    const [address, setAddress] = useState('');
    const addressChangeHandler = useCallback(function _addressChangeHandler(event: any) {
        setAddress(event.target.value);
    }, []);


    const saveHandler = useCallback(function _saveHandler() {

        onSave({
            ...customer,
            address, // editable info,
        });

        closeHandler();
    }, [address]);


    return (
        <Dialog open={open} onClose={closeHandler}>

            <DialogTitle>
                {'Edit customer info'}
            </DialogTitle>

            <DialogContent dividers>
                <TextField
                    placeholder="address"
                    value={address}
                    onChange={addressChangeHandler}
                />
            </DialogContent>

            <DialogActions>
                <Button onClick={saveHandler}>
                    {'Save'}
                </Button>
                <Button onClick={closeHandler}>
                    {'Cancel'}
                </Button>
            </DialogActions>

        </Dialog>
    );
}
Run Code Online (Sandbox Code Playgroud)

控制对话框并可以在保存时调用 API 的父组件

function ComponentXYZ() {


    const [openEditDialgo, setOpenEditDialog] = useState(false);

    const closeDialogHandler = useCallback(function _handleClose() {
        setOpenEditDialog(false);
    }, []);

    const [selectedCustomer, setSelectedCustomer] = useState<Customer>({
        customerId: 0,
        customerName: '',
        address: '',
    });

    function customerEditHandler(customer: any) {
        setSelectedCustomer({ ...customer });
        setOpenEditDialog(true);
    }

    const saveHandler = useCallback(function _saveHandler(customer: Customer) {
        console.log({ customer });
    }, []);

    return (
        <Fragment>

            <EditCustomerDialog
                open={openEditDialgo}
                closeHandler={closeDialogHandler}
                customer={selectedCustomer}
                onSave={saveHandler}
            />

            <div>
                {
                    tablesData.map(customer => (
                        <Stack
                            key={customer.customerId}
                            direction="row">
                            <Typography>
                                {customer.customerName}
                            </Typography>
                            <Button onClick={() => customerEditHandler(customer)}>
                                {'edit info'}
                            </Button>
                        </Stack>
                    ))
                }
            </div>

        </Fragment>
    );

}

Run Code Online (Sandbox Code Playgroud)