Home > Enterprise >  React: Child component doesn't get updated values when reset function is triggered in parent co
React: Child component doesn't get updated values when reset function is triggered in parent co

Time:01-14

I'm struggling for several hours with the following issue:

I have a parent component in which I have some values passed from useState to child 1 (CustomerData) then to child 2 (AddressForm and CustomerForm).

My problem is that when the handleReset() from parent component is triggered, the values from child2 (AddressForm and CustomerForm) are not updated and I don't understand why. I Think that Child 2 components are not rerendering when I reset the values and somehow I need to pass in some other way the stated in the set hook from handleReset().

If somebody can help me solve this issue please. Here are my components:

Parent component:


function WidgetCustomerData(props): JSX.Element {
    const customerDataTest = {
        customerFirstName: 'firstNameTest',
        customerLastName: 'lastNameTest',
        customerPhone: '1313212',
        customerEmail: '[email protected]',
        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;

Child1


export default ({nextStepAction, customerData }: MoleculeSystemManagementCustomerDataProps): JSX.Element => {

  return (
    <div className='c-data'>
      <CustomerForm customerData={customerData} />
      <AddressForm formId='customer' customerData={customerData} />
    </div>
  );
}

Child2


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;

CodePudding user response:

I think the problem is occurring because the state is only being passed to the first child component.

If you look carefully, you'll see that during the passage from the child (1) to child(2) there's no state dealing with it. React is not going to update the value of your props if it's not a state.

Probably, you just need to create a state within the first child. Look the example:

Child 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>
      );
    }

Extra tips: I don't what are the use cases of your project, but I highly recommend you to take a look at React Context API

It's a great idea to use it if you need to pass data through components that need the same data and do cohesive functions.

In a typical React application, data is passed top-down (parent to child) via props, but such usage can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.

CodePudding user response:

it looks like you are setting the state to the same data as it was initialised. you initialise it with customerDataTest and then set it to customerDataTest. same thing

  • Related