Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

State isn't updated on handler call from child to parent

I have a parent component PlannerDetails and a child component PlannerDetailsFooter. Now when I click the button {props.emailConfig.buttonText} doesn’t update with string Send Now, the boolean does though.

// PlannerDetails

import {useState} from "react";
import PlannerDetailsHead from "./PlannerDetailsHead";
import PlannerDetailsBody from "./PlannerDetailsBody";
import PlannerDetailsFooter from "./PlannerDetailsFooter";

const PlannerDetails = (props) => {

    const [emailConfig, setEmailConfig] = useState(
        {
            'email': '',
            'isSent': false,
            'isHidden': true,
            'buttonText': 'Send via Email'
        }
    )

    const emailHandler = (event) => {
        if (event.id === "mail-button") {
            setEmailConfig({...emailConfig, isHidden: false})
            setEmailConfig({...emailConfig, buttonText: 'Send Now'})
        } else {
            setEmailConfig(event.target.value)
        }
    }

    return (
        <div className="details-wrapper relative h-full">
            <PlannerDetailsHead {...props}/>
            <PlannerDetailsBody {...props}/>
            <PlannerDetailsFooter {...props} emailConfig={emailConfig} emailHandler={emailHandler}/>
        </div>
    )
}

export default PlannerDetails
// PlannerDetailsFooter

import {TextField} from "@mui/material";

const PlannerDetailsFooter = (props) => {
    return (
        <div className="details-footer w-full p-4 bottom-0 absolute border-t-1">
            {props.emailConfig.isHidden ? null :
            <TextField
                id="email-input"
                label="Applicant's E-Mail"
                variant="outlined"
                required={true}
                sx={{
                    width: '200px',
                    marginRight: '12px',
                }}
                value={props.emailConfig.email}
                onChange={props.emailHandler}
            />}
            <button id="mail-button"
                    className="send-mail p-2 bg-sx-pink rounded-md shadow-lg text-sx-purple-dark-soft"
                    onClick={props.emailHandler}
            >{props.emailConfig.buttonText}</button>
        </div>
    )
}

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

First you’ll want to debug to confirm whether this condition is true or not:

if (event.id === "mail-button")

Because if it’s not then it looks like this is going to clobber your state object entirely:

setEmailConfig(event.target.value)

So it’s not really clear at all what state update you want to make in that else block. It should probably look like your other state updates, at least structurally:

setEmailConfig({...emailConfig, someProp: 'some value'})

But aside from that, this is incorrect:

setEmailConfig({...emailConfig, isHidden: false})
setEmailConfig({...emailConfig, buttonText: 'Send Now'})

Only one of these will be applied, because they’re both updating different things and state updates are batched and processed asynchronously. So whichever one of these occurs second will overwrite the changes made by the first one. (They will probably be executed in order, but I don’t know if React guarantees that. And in any even, you shouldn’t rely on that.)

Just perform one state update here:

setEmailConfig({...emailConfig, isHidden: false, buttonText: 'Send Now'})

You can perform multiple state updates, making use of the previous updates in the same batch by supplying a callback. For example:

setEmailConfig(prev => {...prev, isHidden: false});
setEmailConfig(prev => {...prev, buttonText: 'Send Now'});

But in this case that’s kind of overkill. You’d use that in more complex logic where it’s possible that you might have multiple separate things to update. But honestly in the majority of cases all you want to do is define the new state and call the setter with that new state, so one state update.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading