[英]Get child state when the action is triggered in parent component in React
[英]React: Child component doesn't get updated values when reset function is triggered in parent component
更新:
我为以下问题苦苦挣扎了几个小时:我有一个父组件,其中我有一些值从 useState 传递给子 1 (CustomerData),然后传递给子 2(-AddressForm 和 -CustomerForm)。
我的问题是,当父组件的 handleReset() 被触发时,child2(AddressForm 和 CustomerForm)的值没有更新,我不明白为什么。 我认为当我重置值时 Child 2 组件不会重新呈现,并且我需要以某种其他方式传递来自 handleReset() 的设置挂钩中所述的其他方式。
如果有人可以帮我解决这个问题。 这是我的组件:
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;
export default ({nextStepAction, customerData }: MoleculeSystemManagementCustomerDataProps): JSX.Element => {
return (
<div className='c-data'>
<CustomerForm customerData={customerData} />
<AddressForm formId='customer' customerData={customerData} />
</div>
);
}
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;
我认为问题的发生是因为 state 仅被传递给第一个子组件。
如果你仔细观察,你会发现在从 child (1) 到 child(2) 的过程中,没有 state 处理它。 如果 props 不是 state,React 不会更新它的值。
可能,您只需要在第一个孩子中创建一个 state。 看例子:
export default ({nextStepAction, customerData }: MoleculeSystemManagementCustomerDataProps): JSX.Element => {
const [addressIsDifferent, setAddressIsDifferent] = useState(true);
const [customerDataState, setCustomerDataState] = useState(customerData)
return (
<div className='c-data'>
<CustomerForm customerData={customerData} />
<AddressForm formId='customer' customerData={customerDataState} />
</div>
);
}
额外提示:我不知道你的项目有哪些用例,但我强烈建议你看看 React Context API
如果您需要通过需要相同数据并执行内聚功能的组件传递数据,那么使用它是个好主意。
在典型的 React 应用程序中,数据通过 props 自上而下(父到子)传递,但对于应用程序中许多组件所需的某些类型的 props(例如语言环境首选项、UI 主题),这种使用可能很麻烦。 Context 提供了一种在组件之间共享这些值的方法,而无需显式地通过树的每个级别传递 prop。
看起来您正在将 state 设置为与初始化时相同的数据。 您使用customerDataTest
对其进行初始化,然后将其设置为customerDataTest
。 一样
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.