Home > Enterprise >  React.js -- state not updating in functional component
React.js -- state not updating in functional component

Time:10-23

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

A huge thank you in advance!

CodePudding user response:

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.

CodePudding user response:

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]
}))
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

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

  • Related