首页 > 解决方案 > Material-UI TextField 失去了对每个 onChange 的关注

问题描述

我正在创建以下组件:

添加药物的组件

它将包含一个对象数组,其中每个对象都是一个处方,带有来自选择的药物名称和一个用于 Dosis 的 TextField。

我的问题是 TextField 失去了对每个 onChange() 的关注并且非常令人沮丧,因为它不能在单个焦点上进行编辑。

这是我的组件:

const MedicineSelect = ({ medications, setMedications, ...props }) => {
    const { medicines } = useMedicines()
    const classes = useStyles()

    const handleChange = (index, target) => {
        // setAge(event.target.value)
        const newMedications = cloneDeep(medications)
        newMedications[index][target.name] = target.value
        setMedications(newMedications)
    }

    const handleAddMedicine = () => {
        const newMedications = cloneDeep(medications)
        newMedications.push({ medicine: '', dosis: '', time: '' })
        setMedications(newMedications)
    }

    const handleDeleteMedicine = (index) => {
        console.log('DELETE: ', index)
        const newMedications = cloneDeep(medications)
        newMedications.splice(index, 1)
        setMedications(newMedications)
    }

    return (
        <Paper style={{ padding: 5 }}>
            <List>
                {medications.map((medication, index) => (
                    <ListItem key={nanoid()} divider alignItems='center'>
                        <ListItemIcon>
                            <Tooltip title='Eliminar'>
                                <IconButton
                                    className={classes.iconButton}
                                    onClick={() => handleDeleteMedicine(index)}
                                >
                                    <HighlightOffOutlinedIcon />
                                </IconButton>
                            </Tooltip>
                        </ListItemIcon>
                        <FormControl className={classes.formControl}>
                            <InputLabel
                                id={`${index}-select-${medication}-label`}
                            >
                                Medicamento
                            </InputLabel>
                            <Select
                                labelId={`${index}-select-${medication}-label`}
                                id={`${index}-select-${medication}`}
                                name='medicine'
                                value={medication.medicine}
                                onChange={(event) =>
                                    handleChange(index, event.target)
                                }
                            >
                                {medicines.map((medicine) => (
                                    <MenuItem
                                        key={nanoid()}
                                        value={medicine.name}
                                    >
                                        {medicine.name}
                                    </MenuItem>
                                ))}
                            </Select>
                        </FormControl>
                        <TextField
                            // fullWidth
                            id={`${index}-text-${medication}`}
                            label='Dosis'
                            name='dosis'
                            onChange={(event) =>
                                handleChange(index, event.target)
                            }
                            value={medication.dosis}
                        />
                    </ListItem>
                ))}
                <Button onClick={handleAddMedicine}>+ agregar</Button>
            </List>
        </Paper>
    )
}

这是我设置组件的地方:

const [medications, setMedications] = useState([
        { medicine: '', dosis: '', time: '' },
    ])
...
<Grid item md={12} xs={12}>
                                <Accordion>
                                    <AccordionSummary
                                        expandIcon={<ExpandMoreIcon />}
                                        aria-controls='panel1a-content'
                                        id='panel1a-header'
                                    >
                                        <Typography variant='h4'>
                                            Tratamiento:
                                        </Typography>
                                    </AccordionSummary>
                                    <AccordionDetails>
                                        <Container disableGutters>
                                            <MedicineSelect
                                                medications={medications}
                                                setMedications={setMedications}
                                            />
                                        </Container>
                                    </AccordionDetails>
                                </Accordion>
                            </Grid>
...

从数组中添加和删除对象非常完美。从选择中选择药物,也很完美。我唯一的问题是在编辑 Dosis TextField 时,每个字符都会失去焦点,我必须再次单击 TextField。

请帮我解决这个问题!!!

标签: javascriptreactjsmaterial-uitextfield

解决方案


经过大量搜索,我终于找到了解决方案。实际上,当使用 nanoid() 创建唯一键时,在每次状态更新时,React 都会重新渲染所有组件,并且由于 List 和 TextField 组件的 id 在每次渲染时都由 nanoid 重新生成,因此 React 会丢失原始值,即这就是焦点丢失的原因。

我所做的是保持键不可切割:

<ListItem key={`medication-${index}`} divider alignItems='center'>

<TextField
    key={`dosis-${index}`}
    fullWidth
    // id={`${index}-dosis-${medication}`}
    label='Dosis'
    name='dosis'
    onChange={(event) =>
        handleChange(index, event.target)
    }
    value={medication.dosis}
/>

推荐阅读