Home > other >  Callback from Child to Parent React
Callback from Child to Parent React

Time:10-22

I am very new to React and this is my first task on an existing project..! Okay, coming to the point, So there is a Parent component ContactForm.js that has child component UserInfoStep.js. There is a button in parent component that I need to enable/disable based on a toggle button in the child component. I have tried using callback but it gives me error..

TypeError: Cannot read properties of undefined (reading 'callbackFunction')

ContactForm.js

const callbackFunction = (isChecked) => {
  //do enable/disable
this.Button.disabled = isChecked;
};

function ContactForm() {
    const [buttonState, setButtonState] = useState(true);
  const { PUID,FirstName, LastName, EurofinsLegalEntity, EurofinsBusinessUnit, StartDate, EndDate, frequency, test, exp, signed, laptop, transfer, existing, newL, categories} = state;

  const steps = [
    <UserInfoStep parentCallback = {this.callbackFunction} {...{  PUID,FirstName, LastName, EurofinsLegalEntity, EurofinsBusinessUnit, StartDate, EndDate}} />];

  return (
    <ContactFormContext.Provider value={{ dispatch }}>
  //some code removed
        <Button
         disabled={buttonState}
          type="submit"

      className={classes.button}
      color="primary"
      variant="outlined"
      onClick={e => {
        e.preventDefault();

        if (isLast) {
          handleSubmit();
        } else {
          goForward();
        }
      }}
    >
      {isLast ? "Submit" : "Next"}
    </Button>
//some code removed
</ContactFormContext.Provider>
);
}

export default ContactForm;

UserInfoStep.js

function UserInfoStep ({ PUID, FirstName, LastName, EurofinsLegalEntity, EurofinsBusinessUnit, StartDate, EndDate }) {
  const { dispatch } = useContext(ContactFormContext);
  const [checked, setChecked] = useState(false);

 const handleChange = () => {
 setChecked((prev) => !prev);

//as soon as this is checked, enable the button in contactForm
sendData(checked);
};

  const sendData = (isChecked) => {
this.parentCallback(isChecked);
//Enabled = isChecked;
};

return(
//some controls
<FormControlLabel
    control={<Switch checked={checked} onChange={handleChange} />}
  />
);

}

export default UserInfoStep;

CodePudding user response:

  1. You're using function components so there's no need to use this.

  2. Your state isn't being used because...

  3. ...your callback function is outside of the component and trying to set this.Button which doesn't exist.

So (this is a very simplified version of your code): move the handler inside the component so that it can update the state directly, and use the button state to inform the disabled property of the button which state it should be in.

const { useState } = React;

function UserInfoStep({ handleChange }) {
  return (
    <button onClick={handleChange}>Toggle parent button</button>
  );
}

function ContactForm() {

  const [ buttonState, setButtonState ] = useState(true);

  function handleChange() {
    setButtonState(!buttonState);
  }

  return (
    <div>
      <div class="child">
        Child component&nbsp;&nbsp;
        <UserInfoStep handleChange={handleChange} />
      </div>
      <div class="parent">
      Parent component&nbsp;&nbsp;
        <button disabled={buttonState}>
          Parent button
        </button>
      </div>
    </div>
  );
};

ReactDOM.render(
  <ContactForm />,
  document.getElementById('react')
);
.child, .parent { margin: 0.5em 0 0.5em 0; }
.child button:hover { cursor: pointer; }
.parent button { background-color: #b3ffcc; }
.parent button:disabled { background-color:  #ff9980; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can have a function inside the ContactForm component which toggles the buttonState. You can then pass that function as a prop to the child component and call that function for enabling/disabling the button.

in ContactForm component For eg:

const toggler = () =>{
 setButtonState(!buttonState);
}

pass this toggler function as a prop to the child component and attach it to the onClick handler of the toggle button.

  • Related