更新:
我认为问题是子组件2没有重新渲染,因为在父组件中触发handleReset()时有相同的 prop 。但我如何使它们重新渲染?我尝试使用useEffect,但没有任何React。
我挣扎了几个小时与以下问题:我有一个父组件,其中一些值从useState传递到子组件1(CustomerData),然后传递到子组件2(-AddressForm和-CustomerForm)。
我的问题是,当父组件的handleReset()被触发时,child2(AddressForm和CustomerForm)的值没有更新,我不明白为什么。我认为当我重置值时,child2组件没有重新呈现,不知何故,我需要以某种其他方式传递handleReset()的set钩子中的声明。
如果有人能帮我解决这个问题,请。以下是我的组件:
父组件:
function WidgetCustomerData(props): JSX.Element {
const customerDataTest = {
customerFirstName: 'firstNameTest',
customerLastName: 'lastNameTest',
customerPhone: '1313212',
customerEmail: 'test@test.com',
customerAddress: 'Musterstraße',
customerAddressNo: '12',
customerZip: '80335',
customerCity: 'Berlin',
deviceAddress: 'Straße',
deviceAddressNo: '152',
deviceZip: '32214',
deviceCity: 'Hamburg',
};
const [customerData, setCustomerData] = useState({
addressValue: customerDataTest.customerAddress,
addressValueNr: customerDataTest.customerAddressNo,
addressValueZip: customerDataTest.customerZip,
addressValueCity: customerDataTest.customerCity,
customerFirstName: customerDataTest.customerFirstName,
customerLastName: customerDataTest.customerLastName,
customerPhone: customerDataTest.customerPhone,
customerEmail: customerDataTest.customerEmail,
deviceAddress: customerDataTest.deviceAddress,
deviceAddressNo: customerDataTest.deviceAddressNo,
deviceZip: customerDataTest.deviceZip,
deviceCity: customerDataTest.deviceCity
})
const handleClose = () => {
props.handleClose();
}
const handleSubmit = async (e) => {
e && e.preventDefault();
const formUrl = 'https://fetch.mock/widget-customer-data/addCustomerData';
const formData = new FormData(e.target);
for (const [name, value] of formData) {
console.log(`${name}: ${value}`);
}
const response = await fetch(formUrl.toString(), {
method: 'POST',
body: formData,
credentials: 'same-origin',
});
const data = await response.json();
};
const handleReset = () => {
console.log('handleReset ----');
setCustomerData({
addressValue: customerDataTest.customerAddress,
addressValueNr: customerDataTest.customerAddressNo,
addressValueZip: customerDataTest.customerZip,
addressValueCity: customerDataTest.customerCity,
customerFirstName: customerDataTest.customerFirstName,
customerLastName: customerDataTest.customerLastName,
customerPhone: customerDataTest.customerPhone,
customerEmail: customerDataTest.customerEmail,
deviceAddress: customerDataTest.deviceAddress,
deviceAddressNo: customerDataTest.deviceAddressNo,
deviceZip: customerDataTest.deviceZip,
deviceCity: customerDataTest.deviceCity
})
};
return (
<div className="customer-data">
<Dialog
onClose={handleClose}
open={props.open}
aria-labelledby="customized-dialog-title"
PaperProps={{
style: { borderRadius: 20, minWidth: '80%', maxHeight: 'fit-content' },
}}>
<DialogTitle id="customized-dialog-title" onClose={handleClose} />
<Typography style={{ marginTop: 20, paddingLeft: 48, fontSize: 32, fontWeight: 600 }}>Kundendaten bearbeiten</Typography>
{/* <DialogContent> */}
<form onSubmit={handleSubmit}>
<div style={{ paddingLeft: 48, paddingRight:48 }}>
<CustomerData
customerData={customerData}
/>
</div>
<DialogActions>
<ResetButton onClick={handleReset} variant="contained" color="primary">
Reset
</ResetButton>
<SaveButton type="submit" variant="contained" color="primary">
Save
</SaveButton>
</DialogActions>
</form>
{/* </DialogContent> */}
</Dialog>
</div>
);
}
export default WidgetCustomerData;
儿童1
export default ({nextStepAction, customerData }: MoleculeSystemManagementCustomerDataProps): JSX.Element => {
return (
<div className='c-data'>
<CustomerForm customerData={customerData} />
<AddressForm formId='customer' customerData={customerData} />
</div>
);
}
儿童2
function AddressForm({formId customerData }): JSX.Element {
const classes = useStyles();
const { addressValue, addressValueNr, addressValueZip, addressValueCity, deviceAddress, deviceAddressNo, deviceZip, deviceCity } = customerData;
return (
<Grid container className={classes.borderedRow}>
<Grid item xs={12} sm={6} md={3} className={classes.formColumn}>
<div>
<InputField type='label' id='address' name={`${formId}-address`} value={formId === 'customer' ? addressValue : deviceAddress} label={'Street'} />
</div>
</Grid>
<Grid item xs={12} sm={6} md={3} className={classes.formColumn}>
<InputField type='label' id='city' name={`${formId}-city`} value={formId === 'customer' ? addressValueNr : deviceAddressNo} label={'Number'} />
</Grid>
<Grid item xs={12} sm={6} md={3} className={classes.formColumn}>
<InputField type='label' id='state' name={`${formId}-state`} value={formId === 'customer' ? addressValueZip : deviceZip} label={'ZIP'} />
</Grid>
<Grid item xs={12} sm={6} md={3} className={classes.formColumn}>
<InputField type='label' id='zip' name={`${formId}-zip`} value={formId === 'customer' ? addressValueCity : deviceCity} label={'ORT'} />
</Grid>
</Grid>
);
}
export default AddressForm;
2条答案
按热度按时间tp5buhyn1#
我认为问题的发生是因为状态只传递给了第一个子组件。
如果你仔细观察,你会发现在从child(1)到child(2)的过程中,没有状态处理它,如果它不是状态,React不会更新你的props的值。
也许,你只需要在第一个子节点中创建一个状态。
儿童1
额外提示:我不知道您项目的用例是什么,但我强烈建议您看一看ReactContext API
如果您需要通过需要相同数据的组件传递数据并执行内聚函数,那么使用它是一个很好的主意。
在一个典型的React应用程序中,数据是通过props自上而下(父到子)传递的,但是这种用法对于应用程序中许多组件所需的某些类型的props(例如区域设置首选项、UI主题)来说可能很麻烦。上下文提供了一种在组件之间共享值的方法,而不必显式地通过树的每一级传递prop。
mum43rcc2#
它看起来象你正在设置状态到相同的数据作为它是initialised.你initialised它与
customerDataTest
并且然后设置它到customerDataTest
.同样的事情