meeshaa
meeshaa

Reputation: 163

Array not updating on first click

Making a small todo app, I want to add the functionality that when the task is checked, the checked task goes into an array. On first click the task consoles an empty array, then when unchecked and checked again, my array gets updated. Any reason as to why it takes two click for array to update?

function SelectTodo({ todo }) {
  const [checkboxChecked, setCheckboxChecked] = React.useState([]);

  const handleInputChange = (e) => {
    const checked = e.target.checked;
    let value = e.target.value;

    if (checked) {
      setCheckboxChecked((prevChecked) => [...prevChecked, value]);
      console.log("checkBoxArrray:" + checkboxChecked);
    } else {
      console.log("unchecked");
    }
  };

  return (
    <label className="todo-list__label">
      <div className="form-check form-check-inline">
        <input
          className="form-check-input"
          type="checkbox"
          name="task"
          id="inlineCheckboxh1"
          value={todo}
          onChange={handleInputChange}
        />
        <label className="form-check-label" htmlFor="inlineCheckboxh1">
          {todo}
        </label>
      </div>
    </label>
  );
}

ReactDOM.render(<SelectTodo todo={5} />, document.getElementById("root"));
<div id="root" />
<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>

Upvotes: 0

Views: 1580

Answers (3)

Arti
Arti

Reputation: 47

Check following solution , there is some condition for adding data you can skip , from this you can get instant updated array

  const [updated_chat, setUpdatedChat] = useState([]);
  const [messages_array, setMessagesArray] = useState([]);


  if (onMessage && userData?.user != text["userId"]) {
    if (updated_chat) {
      updated_chat.push(text);
      setMessagesArray(prevChecked => [...prevChecked, text]);
    }
  }

console.log(messages_array);

Upvotes: 0

Janez Kuhar
Janez Kuhar

Reputation: 4266

You can't access the updated state from the current state. See useState set method not reflecting change immediately for more info.

What you can do is trigger an effect when a state variable gets updated and print your updated array there:

React.useEffect(() => {
  console.log("checkBoxArrray:" + checkboxChecked);
}, [checkboxChecked]);

The solution proposed by Nisanth Reddy also works.


Fully working example:

function SelectTodo({ todo }) {
  const [checkboxChecked, setCheckboxChecked] = React.useState([]);

  const handleInputChange = (e) => {
    const checked = e.target.checked;
    let value = e.target.value;

    if (checked) {
      setCheckboxChecked((prevChecked) => [...prevChecked, value]);
    } else {
      console.log("unchecked");
    }
  };
  
  React.useEffect(() => {
    console.log("checkBoxArrray:" + checkboxChecked);
  }, [checkboxChecked]);

  return (
    <label className="todo-list__label">
      <div className="form-check form-check-inline">
        <input
          className="form-check-input"
          type="checkbox"
          name="task"
          id="inlineCheckboxh1"
          value={todo}
          onChange={handleInputChange}
        />
        <label className="form-check-label" htmlFor="inlineCheckboxh1">
          {todo}
        </label>
      </div>
    </label>
  );
}

ReactDOM.render(<SelectTodo todo={5} />, document.getElementById("root"));
<div id="root" />
<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>

Upvotes: 1

Nisanth Reddy
Nisanth Reddy

Reputation: 6405

Setting state is as async process in React.

This means, calling setCheckboxChecked and the immediately trying to read the value of checkboxChecked is going to give you the current value and not the update value.

This means that the array is actually getting updated, but you are only logging the old value, so it seems like it is taking two clicks.

If you want to check the updated value, do this.

setCheckboxChecked((prevChecked) => {
    const updated = [...prevChecked, value];
    console.log(updated);
    return updated;
});

Upvotes: 1

Related Questions