0

I have a functional component with a state hook called "checked" that is an array of Booleans for a list of checkboxes. When a checkbox is clicked, I have an event handler that updates state so the checkbox will render a check or an empty box.

According to the console.logs in my function, state is updating, but the checkboxes are not responsive in the browser and dev tools confirm that state is not updating. If I manually toggle state using the dev tools the checkboxes work just fine, so I believe it's an issue with state not updating. Any advice would be very appreciated!

import React, { useState, useContext } from 'react';

export default function MessengerCheckboxes() {
 const [checked, setChecked] = useState([false, false, false]);

...

 const handleChangeChild = (event) => {
   console.log('Currently state is: ' + checked); // Currently state is: [false, false, false]

   let index = parseInt(event.target.id.slice(0, 1));
   let localChecked = checked; //
   localChecked[index] = !checked[index];
    
   console.log('State should be: ' + localChecked); //State should be: [true, false, false] [[for example]]
   setChecked(localChecked);
    
   setTimeout(() => { // Added setTimeout for troubleshooting to make sure I wasn't calling state too quickly after setting it
       console.log('State is now: ' + checked); // State is now: [true, false, false] [[but won't trigger re-render and dev tools show state is [false, false, false]]
   }, 1 * 1000);
 };
}

Image of my console.log

Image of my dev tools

3
  • Also post the jsx Commented Oct 22, 2021 at 17:31
  • This is not how you should update state. Do not mutate the existing array by doing array[idx] = true. You have to reassign the entire array with setChecked([...]). Read about mutable and immutable objects Commented Oct 22, 2021 at 17:32
  • You're mutating state. Don't mutate state. Commented Oct 22, 2021 at 17:41

2 Answers 2

2

you shouldn't update state like that.

In situations like this, a bit more complex state object is required. I like to use an object to keep state for each item in the list. Check this link: https://codesandbox.io/s/checkbox-state-https-stackoverflow-com-questions-69680938-react-js-state-not-updating-in-functional-component-di0dd

import "./styles.css";
import { useState } from "react";

export default function App() {
  // 1.
  const stateObj = {
    cb1: false,
    cb2: false,
    cb3: false
  };
  const [cbState, setCbState] = useState(stateObj);
  const handleCb = (event) => {
    console.log(event.target.name, event.target.checked);
    // 4.
    setCbState({ ...cbState, [event.target.name]: event.target.checked });
  };
  return (
    <div>
      <input
        type="checkbox"
        name="cb1" // 2.
        onChange={handleCb}
        value={cbState["cb1"]} // 3.
      />
      <input
        type="checkbox"
        name="cb2"
        onChange={handleCb}
        value={cbState["cb2"]}
      />
      <input
        type="checkbox"
        name="cb3"
        onChange={handleCb}
        value={cbState["cb3"]}
      />
    </div>
  );
}

So for take away, in steps:

  1. create/prepare state object - keys will be used as names to html elements
  2. set name attribute for html element - use same keys from 1.
  3. set value attribute for html element - bracket notation using state['key']. This is how you achieve controlled components
  4. set state in a way that you persist existing data/values (using spread operator) + update (bracket notation for accessing the properties). In this example we achieve it with event name and checked attributes.
Sign up to request clarification or add additional context in comments.

Comments

0

Well you'd have read the comments that you shouldn't mutate the state. So to handle such situations, I usually to do like this:-

setChecked(data => ({
      ...data,
      [ind]: !checked[ind]
}))

P.S. - Do read about different approaches of handling states, it's gonna help you alot in the longer run. :)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.