Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

161
Visualizações
Why only 1 function out of two gets executed in onClick event

I am building a simple react app that is meant to pass several functions responsible to update the same state object in the parent component, but for some reason, only one of two functions gets executed when triggered by an onClick event in a children component or at least so it seems, let me show you some code:

Children component:

        <button id='but2' onClick={()=>{
        props.isBeginner(true); 
        props.nextStep(2)
        }} 
        className={classes.chooseButton} >Choice number 1</button>

Parent component functions:

isBeginner(b){
setUser({...user,first_timer:b})}

nextStep =(step)=>{
setUser({...user,setup_step:step})}

Between the children and the parent components, there is a middle component responsible to sort the right child component to render, it does that through a switch operator:

switch(step){
    
    
    case 1 :{return <StepOne user={props.user} nextStep={props.nextStep} 
    isBeginner={props.isBeginner} />};
    break;
    case 2 :{return <StepTwo whatMedium={props.whatMedium} user= 
    {props.user}  nextStep={props.nextStep}/>}  
    break;
    case 3 :{return <StepThree user={props.user} nextStep= 
    {props.nextStep}/>}  
    break;
    case 4 :{return <StepFourth nextStep={props.nextStep}/>}  
    break;

    default:{<StepOne isBeginner={props.isBeginner} nextStep={ 
    props.nextStep}/>}

    }

Why can't I update the state of the parent component using two different functions (passed down to children components) to update different values of the same (state) object?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Both functions get executed, but it seems like only one of them is because each of them uses the in-scope user state member, which is stale after the first update is done. So the second update doesn't include the first update's change.

When updating state based on existing state, to avoid updates with stale information it's best to use the callback form of the state setter:

isBeginner(b){
    setUser(user => ({...user, first_timer: b}));
}
// ...
nextStep = (step) => {
    setUser(user => ({...user, setup_step: step}));
};

That way, each state update is done with an up-to-date state value.

Here's a simpler example:

const {useState} = React;

const classes = {
    chooseButton: "",
};

const Child = (props) => {
    return <button
        id='but2' onClick={() => {
            props.isBeginner(true); 
            props.nextStep(2)
        }} 
        className={classes.chooseButton}
        >
        Choice number 1
    </button>;
};

const Wrong = () => {
    const [user, setUser] = useState({
        first_timer: false,
        setup_step: 1,
    });

    const isBeginner = (b) => {
        setUser({...user,first_timer:b});
    };
    const nextStep = (step) => {
        setUser(({...user,setup_step:step}));
    };

    return <div>
        <h2>Wrong</h2>
        <div>first_timer: {String(user.first_timer)}</div>
        <div>step: {user.setup_step}</div>
        <Child isBeginner={isBeginner} nextStep={nextStep} />
    </div>;
};

const Right = () => {
    const [user, setUser] = useState({
        first_timer: false,
        setup_step: 1,
    });

    const isBeginner = (b) => {
        setUser(user => ({...user, first_timer: b}));
    };
    const nextStep = (step) => {
        setUser(user => ({...user, setup_step: step}));
    };

    return <div>
        <h2>Right</h2>
        <div>first_timer: {String(user.first_timer)}</div>
        <div>step: {user.setup_step}</div>
        <Child isBeginner={isBeginner} nextStep={nextStep} />
    </div>;
};

ReactDOM.render(
    <div>
        <Wrong />
        <hr />
        <Right />
    </div>,
    document.getElementById("root")
);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>


Side note: I'd expect a function called nextStep to handle advancing to the next step itself rather than accepting a parameter for the step value. For instance:

nextStep = () => {
    setUser(user => ({...user, setup_step: user.setup_step + 1}));
};

Just for what it's worth...

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda