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:
You're using function components so there's no need to use
this
.Your state isn't being used because...
...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
<UserInfoStep handleChange={handleChange} />
</div>
<div class="parent">
Parent component
<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.