繁体   English   中英

反应:在父组件中触发重置 function 时,子组件不会获得更新的值

[英]React: Child component doesn't get updated values when reset function is triggered in parent component

更新:

我认为问题是 Child 2 组件没有重新渲染,因为在父组件中触发 handleReset() 时有相同的道具。但是我怎样才能让它们重新渲染? 我尝试使用 useEffect 但没有任何反应。

我为以下问题苦苦挣扎了几个小时:我有一个父组件,其中我有一些值从 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;

孩子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;

我认为问题的发生是因为 state 仅被传递给第一个子组件。

如果你仔细观察,你会发现在从 child (1) 到 child(2) 的过程中,没有 state 处理它。 如果 props 不是 state,React 不会更新它的值。

可能,您只需要在第一个孩子中创建一个 state。 看例子:

孩子 1

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM