skip to Main Content

I am mapping some data into a table. Each row of the table has a checkbox. In order to manage the state of the checkboxes I am adding or removing the checkbox id to the array.

I want to determine if a box should be checked by seeing if the id is contained in the array.

  const [bulkUpdateIds, setBulkUpdateIds] = useState([
    '7a678176-2703-4f89-63cb-08dc3e4b1e2f',
  ])

  function handleCheck(id) {
    console.log('running', bulkUpdateIds)
    const idArray = bulkUpdateIds
    if (idArray.includes(id)) {
      const index = idArray.indexOf(id)
      idArray.splice(index, 1)
      setBulkUpdateIds(idArray)
    } else {
      idArray.push(id)
      setBulkUpdateIds(idArray)
    }
  }

   cellRenderer: (params) => {
      return (
         <input
            type="checkbox"
            checked={bulkUpdateIds.includes(
                params.data.soVRecordID
            )}
            onChange={() =>
                handleCheck(params.data.soVRecordID)
            }
      />
  )
},

I can see that the id is being added and removed from the list, however it seems like the logic to determine if the box is checked or not only fires once.

2

Answers


  1. Consider creating a new array to setBulkUpdateIds, instead of mutating the existing array value. As per the documentation:

    In JavaScript, arrays are just another kind of object. Like with objects, you should treat arrays in React state as read-only. This means that you shouldn’t reassign items inside an array like arr[0] = 'bird', and you also shouldn’t use methods that mutate the array, such as push() and pop().

    Instead, every time you want to update an array, you’ll want to pass a new array to your state setting function. To do that, you can create a new array from the original array in your state by calling its non-mutating methods like filter() and map(). Then you can set your state to the resulting new array.

    Thus, we tweak the logic in handleCheck() to avoid array mutation and instead pass a whole new array value each time:

    const { useState } = React;
    
    function App() {
      const [bulkUpdateIds, setBulkUpdateIds] = useState([
        "7a678176-2703-4f89-63cb-08dc3e4b1e2f",
      ]);
    
      function handleCheck(id) {
        console.log("running", bulkUpdateIds);
        if (bulkUpdateIds.includes(id)) {
          const index = bulkUpdateIds.indexOf(id);
          setBulkUpdateIds([
            ...bulkUpdateIds.slice(0, index),
            ...bulkUpdateIds.slice(index + 1),
          ]);
        } else {
          setBulkUpdateIds(bulkUpdateIds.concat(id));
        }
      }
    
      const foo = {
        cellRenderer: (params) => {
          return (
            <input
              type="checkbox"
              checked={bulkUpdateIds.includes(params.data.soVRecordID)}
              onChange={() => handleCheck(params.data.soVRecordID)}
            />
          );
        },
      };
    
      return (
        <React.Fragment>
          <foo.cellRenderer
            data={{ soVRecordID: "7a678176-2703-4f89-63cb-08dc3e4b1e2f" }}
          />
          <foo.cellRenderer data={{ soVRecordID: "foo" }} />
        </React.Fragment>
      );
    }
    
    ReactDOM.createRoot(document.getElementById("app")).render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <div id="app"></div>
    Login or Signup to reply.
  2. Wongjn has explained it well.

    However, a quick fix in your case would be replacing the const idArray = bulkUpdateIds; with const idArray = bulkUpdateIds.slice(0); This will make a copy of ‘bulkUpdateIds’ for further processing.

    So the new handleCheck() would be-

      function handleCheck(id) {
        console.log('running', bulkUpdateIds)
        const idArray = bulkUpdateIds.slice(0);
        if (idArray.includes(id)) {
          const index = idArray.indexOf(id)
          idArray.splice(index, 1)
          setBulkUpdateIds(idArray)
        } else {
          idArray.push(id)
          setBulkUpdateIds(idArray)
        }
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search