Alfred
Alfred

Reputation: 684

Prevent checkboxes from re-rendering in React

I'm trying to render multiple checkboxes based on dynamic return data and have their checked status stored in a local state.

However the performance starts to degrade when higher number of checkboxes are generated. I noticed the issue is due to the constant re-rendering of ALL the checkboxes whenever any one of them is checked (checkbox states are all stored in the same object with different keys)

Here is my sample code and a codesandbox link to see the actual performance issue (notice the delay when a checkbox is selected)

export default function App() {
  const [checkboxResponse, setCheckboxResponse] = useState([]);
  const [checkboxList, setCheckboxList] = useState();
  const [checkboxStates, setCheckboxStates] = useState({});

  useEffect(() => {
    //Generate dummy data
    const dummyData = [];

    for (let i = 0; i < 1000; i++) {
      dummyData.push(i.toString());
    }

    //Set dummyData as checkbox dynamic data
    setCheckboxResponse(dummyData);
  }, []);

  useEffect(() => {

    //When checkbox is clicked, add to local checkbox states object
    const checkboxChange = key => event => {
      setCheckboxStates({ ...checkboxStates, [key]: event.target.checked });
    };

    //Check if data is available
    if (checkboxResponse) {
      const checkboxes = checkboxResponse.map(key => {
        const value = checkboxStates[key] ? checkboxStates[key] : false;

        //Render checkbox
        return (
          <FormControlLabel
            key={key}
            checked={value}
            control={
              <Checkbox
                size="small"
                value={key}
                onChange={checkboxChange(key)}
              />
            }
            label={key}
          />
        );
      });

      setCheckboxList(checkboxes);
    }
  }, [checkboxResponse, checkboxStates]);

  return (
    <div className="App">
      {checkboxList}
    </div>
  );
}

CodeSandbox

It seems that whenever checkboxStates is changed, the useEffect hook is re-run, triggering a re-render of all the checkboxes again.

Is it possible to prevent React from re-rendering all the checkboxes again whenever the state is changed? Or do we have to create a separate state for every single checkbox dynamically?

Any help would be greatly appreciated.

Upvotes: 3

Views: 2591

Answers (1)

Rostyslav
Rostyslav

Reputation: 2866

You can use React.memo to prevent re-render of unchanged check-boxes. Like this:

import React, { useState, useEffect } from "react";
import { Checkbox, FormControlLabel } from "@material-ui/core";
import "./styles.css";

export default function App() {
  const [checkboxResponse, setCheckboxResponse] = useState([]);
  const [checkboxStates, setCheckboxStates] = useState({});

  //When checkbox is clicked, add to local checkbox states object
  const checkboxChange = key => event => {
    setCheckboxStates({ ...checkboxStates, [key]: event.target.checked });
  };

  useEffect(() => {
    //Generate dummy data
    const dummyData = [];

    for (let i = 0; i < 1000; i++) {
      dummyData.push(i.toString());
    }

    //Set dummyData as checkbox dynamic data
    setCheckboxResponse(dummyData);
  }, []);

  return (
    <div className="App">
      {checkboxResponse.map(key => {
        const value = checkboxStates[key] ? checkboxStates[key] : false;

        //Render checkbox
        return (
          <FormControlLabel
            key={key}
            checked={value}
            control={<MemoCheckbox key={key} checkboxChange={checkboxChange} />}
            label={key}
          />
        );
      })}
    </div>
  );
}

const CustomCheckbox = ({ key, checkboxChange }) => (
  <Checkbox size="small" value={key} onChange={checkboxChange(key)} />
);

const MemoCheckbox = React.memo(
  CustomCheckbox,
  (prev, next) => prev.key === next.key
);

However, it might still be not fast enough as when you click the checkbox it still loops trough .map and creates elements.

Here is docs reference for Memo

Upvotes: 2

Related Questions