gpt4 book ai didi

javascript - 动态表单为第一个和第二个输入返回相同的值

转载 作者:行者123 更新时间:2023-12-05 01:04:59 25 4
gpt4 key购买 nike

我正在使用 Material UI https://mui.com/ 创建自定义动态表单库作为我的 React Js 应用程序的组件。

这里是动态表单组件的初始状态。 enter image description here

正如我们所见,动态表单组件仅从一个交付点表单开始。我们可以通过单击“添加交货”按钮添加另一个交货点表格。这是单击“添加交付”按钮后的示例。

enter image description here

问题是:在我们输入第一个或第二个表单之一后,第一个表单和第二个表单具有相同的值(如果有多个表单),如下面的屏幕截图所示。这不是我想要的条件。

enter image description here

但其余的(第三、第四等)形式是独一无二的,如下面的屏幕截图所示。这是我想要的条件。

enter image description here

这是简单的工作代码:

DeliveryPoint.jsx

const DeliveryPoint = (props) => {
const {
initialFormObject,
formObject,
setFormObject,
collapseObject,
setCollapseObject
} = props;

const classes = useStyles();

const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];

const handleFormObjectChange = (inputEvent, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];
deliveryPointListData[inputIndex][inputEvent.target.name] =
inputEvent.target.value;

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleDatePickerChange = (inputNewValue, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];
deliveryPointListData[inputIndex].deliveryDate = inputNewValue;

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleCollapseChange = (inputIndex) => {
let deliveryPointListData = [...collapseObject.deliveryPointList];
deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];

setCollapseObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleAddFormItemButtonClick = () => {
let deliveryPointListData = [...formObject.deliveryPointList];
deliveryPointListData.push(deliveryPointBaseObject);

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));

deliveryPointListData = [...collapseObject.deliveryPointList];
deliveryPointListData.push(false);

setCollapseObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleDeleteFormItemButtonClick = (inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];
deliveryPointListData.splice(inputIndex, 1);

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));

deliveryPointListData = [...collapseObject.deliveryPointList];
deliveryPointListData.splice(inputIndex, 1);

setCollapseObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

return (
<>
{formObject.deliveryPointList.map((item, index) => (
<Box key={index} className={classes.formItemContainer}>
<Box className={classes.formItemTitleContainer}>
{/* TITLE */}
<Typography variant="h6">
{index === 0 ? `Delivery point` : `#${index + 1} Delivery point`}
</Typography>

{/* ADD OR DELETE BUTTON */}
{index === 0 ? (
<Button
className={classes.formItemTitleButton}
variant="outlined"
startIcon={<IconAdd />}
onClick={handleAddFormItemButtonClick}
>
Add Delivery
</Button>
) : (
<Button
className={classes.formItemTitleButton}
variant="outlined"
startIcon={<IconRemove />}
color="error"
onClick={() => handleDeleteFormItemButtonClick(index)}
>
Remove Delivery
</Button>
)}
</Box>

{/* CONSIGNEE */}
<FormControl
required
variant="outlined"
className={classes.formItemInput}
>
<InputLabel>Consignee</InputLabel>

<OutlinedInput
label="Consignee"
type="text"
name="consignee"
value={item.consignee}
onChange={(event) => handleFormObjectChange(event, index)}
/>

<FormHelperText>
Search for name, street, city, or state by typing in the box.
</FormHelperText>
</FormControl>

{/* DELIVERY DATE */}
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
disableFuture
label="Select Delivery Date"
openTo="year"
views={["year", "month", "day"]}
value={item.deliveryDate}
onChange={(newValue) => handleDatePickerChange(newValue, index)}
renderInput={(params) => (
<TextField
required
className={classes.formItemInput}
{...params}
/>
)}
/>
</LocalizationProvider>

{/* COLLAPSE */}
<Collapse
in={collapseObject.deliveryPointList[index]}
timeout="auto"
unmountOnExit
className={classes.formItemCollapse}
>
{/* DELIVERY INSTRUCTION */}
<FormControl variant="outlined" className={classes.formItemInput}>
<InputLabel>Delivery Instructions</InputLabel>

<OutlinedInput
label="Delivery Instructions"
type="text"
name="deliveryInstruction"
value={item.deliveryInstruction}
onChange={(event) => handleFormObjectChange(event, index)}
/>
</FormControl>
</Collapse>

{/* EXPAND BUTTON */}
<Button
variant="contained"
disableElevation
startIcon={
collapseObject.deliveryPoint ? (
<IconArrowDropUp />
) : (
<IconArrowDropDown />
)
}
className={classes.formItemButtonExpand}
onClick={() => handleCollapseChange(index)}
>
{collapseObject.deliveryPoint
? "Hide full data entry"
: "Fill in more complete data?"}
</Button>
</Box>
))}
</>
);
};

export default DeliveryPoint;

App.jsx

const App = () => {
const classes = useStyles();

const initialFormObject = {
// DELIVERY POINT
deliveryPointList: [
{
consignee: "",
deliveryDate: new Date(),
deliveryInstruction: ""
}
]
// OTHER OBJECT ITEMS HERE
};

const initialCollapseObject = {
deliveryPointList: [false]
// OTHER LIST ITEMS HERE
};

const [formObject, setFormObject] = useState(initialFormObject);
const [collapseObject, setCollapseObject] = useState(initialCollapseObject);

return (
<Box className={classes.pageRoot}>
{/* FORM */}
<Box className={classes.formContainer}>
{/* DELIVERY POINT */}
<DeliveryPoint
initialFormObject={initialFormObject}
formObject={formObject}
setFormObject={setFormObject}
collapseObject={collapseObject}
setCollapseObject={setCollapseObject}
/>
</Box>
</Box>
);
};

export default App;

这里是完整的演示 https://codesandbox.io/s/stackoverflow-dynamic-form-wxrmd0

重现步骤:

  1. 点击“添加配送”按钮两次。所以会有 3 个交货点表格。
  2. 更改第一个交货点表格中的“收货人”或“交货日期”。因此,第二个交货点表单将与第一个表单具有相同的值。

我的状态管理出了什么问题,解决办法是什么?

注意:您可以将 Material UI 中的 OultinedInput 组件假定为 HTML input 元素。

最佳答案

问题

您正在改变 handleFormObjectChangehandleDatePickerChange 处理程序中的状态。

const handleFormObjectChange = (inputEvent, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];

// Mutates the nested property!!
deliveryPointListData[inputIndex][inputEvent.target.name] =
inputEvent.target.value;

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleDatePickerChange = (inputNewValue, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];

// Mutates the nested property!!
deliveryPointListData[inputIndex].deliveryDate = inputNewValue;

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

解决方案

确保您对所有正在更新的属性和嵌套属性进行浅拷贝。这可确保所有更新都会创建新的对象引用。

const handleFormObjectChange = (inputEvent, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];

deliveryPointListData[inputIndex] = {
...deliveryPointListData[inputIndex], // <-- shallow copy
[inputEvent.target.name]: inputEvent.target.value
};

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

const handleDatePickerChange = (inputNewValue, inputIndex) => {
let deliveryPointListData = [...formObject.deliveryPointList];

deliveryPointListData[inputIndex] = {
...deliveryPointListData[inputIndex], // <-- shallow copy
deliveryDate: inputNewValue,
};

setFormObject((current) => ({
...current,
deliveryPointList: deliveryPointListData
}));
};

Edit dynamic-form-returns-the-same-value-for-the-first-and-second-input

关于javascript - 动态表单为第一个和第二个输入返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71263503/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com