0

Here the array (Boolean):

  const [state, setState] = React.useState({
    [`${"checkedA"+index}`]: false, //checkedA0
    [`${"checkedB"+index}`]: false, //checkedB0
    [`${"checkedC"+index}`]: false, //checkedC0
    [`${"checkedD"+index}`]: false, //checkeD0

  });

And the problem code:

    const [countChecked, setCountChecked] = React.useState(0);
    const [previous, setPrevious] = React.useState(0);

    const handleChange = (event) => {


    if(countChecked<1){

      setState({ ...state, [event.target.name]: event.target.checked }); //WORK
      setCountChecked(countChecked+1); //WORK
      setPrevious(event.target.name); //WORK

    }else{

      setState({ ...state, [previous]: false }); //WORKS 
      //setState({ ...state, [event.target.name]: event.target.checked }); //NO WORKS

    }

  };

I don't undestand why if I use multiple times the setState is not working only works one time(line) inside else statement. Thanks!

3
  • Your state is an object, not array. Commented May 7, 2020 at 9:24
  • es.reactjs.org/docs/hooks-state.html and es.reactjs.org/docs/… Commented May 7, 2020 at 9:25
  • You are using setState to update the previous state instead you need to use setPrevious for that. If I am correct not wrong are trying to get what is checked previously among the four checkboxes? For what purpose have you used the count? Do you need to add count everytime user click on checkbox or only when it mark true or whether it is used for just toggel? Commented May 7, 2020 at 9:43

3 Answers 3

2

setState calls the render method and control is not coming back to else block after the first setState method call. Just use a single setState method for both changes, like:

setState({ ...state, [previous]: false, [event.target.name]: event.target.checked });
Sign up to request clarification or add additional context in comments.

Comments

1

The issue is simple.

In the else statement in both the state updates you spread the previous state and pass in the newly updated value. However you must know what state updates in handlers are batched, i.e if you call setState multiple times, the result of all state updates are batched into a single one and updated

While batching the change that you made to [previous] state is lost because the next call to state update also spreads the state and since state updates are async state in

 setState({ ...state, [event.target.name]: event.target.checked }); 

will also refer the original state before any setState was called

The solution here to make all the updates in a single setState call like

  setState({ 
    ...state, 
   [previous]: false,
   [event.target.name]: event.target.checked 
  }); 

However you must note that whenever you are using previous state like you do above its better to use functional setState and also store the event values before you use them since Synthetic events are reused and nullified by React

const { name, checked } = e.target;
setState(prevState => ({ 
    ...prevState, 
   [previous]: false,
   [name]: checked 
  }));

In your if block all three state updates work because when they are batched they refer to different state updaters

Comments

0

Here is the working code of your logic:

  const index = 0;
  const [state, setState] = React.useState({
    [`${"checkedA"+index}`]: false,
    [`${"checkedB"+index}`]: false,
    [`${"checkedC"+index}`]: false,
    [`${"checkedD"+index}`]: false,
  });

  const [countChecked, setCountChecked] = React.useState(0);
  const [previous, setPrevious] = React.useState('');

  const handleChange = (event) => {
    if(countChecked < 1) {
      setState({ ...state, [event.target.name]: event.target.checked });
      setCountChecked(count => count + 1);
      setPrevious(event.target.name);
    } else {
      setState({ ...state, [event.target.name]: event.target.checked });
      setPrevious(false);
    }
  }

  return (
    <div className="membership-all-steps">
      <Checkbox
        name={`${"checkedA"+index}`}
        label="checkedA0"
        onChange={handleChange}
      />
      <Checkbox
        name={`${"checkedB"+index}`}
        label="checkedB0"
        onChange={handleChange}
      />
      <Checkbox
        name={`${"checkedC"+index}`}
        label="checkedC0"
        onChange={handleChange}
      />
      <Checkbox
        name={`${"checkedD"+index}`}
        label="checkedD0"
        onChange={handleChange}
      />
    </div>
  );
}

But still I am not sure what you want to achieve with countChecked & previous state. If you explain for what purpose you are using these state, may be I will help you out with your logic as well. Thanks!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.