Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React setting the state of all rendered items with .map in parent component

I have a parent component with a handler function:

  const folderRef = useRef();
  const handleCollapseAllFolders = () => {
    folderRef.current.handleCloseAllFolders();
  };

In the parent, I’m rendering multiple items (folders):

        {folders &&
          folders.map(folder => (
            <CollapsableFolderListItem
              key={folder.id}
              name={folder.name}
              content={folder.content}
              id={folder.id}
              ref={folderRef}
            />
          ))}

In the child component I’m using the useImperativeHandle hook to be able to access the child function in the parent:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 const [isFolderOpen, setIsFolderOpen] = useState(false);
  // Collapse all
  useImperativeHandle(ref, () => ({
    handleCloseAllFolders: () => setIsFolderOpen(false),
  }));

The problem is, when clicking the button in the parent, it only collapses the last opened folder and not all of them.

Clicking this:

 <IconButton
            onClick={handleCollapseAllFolders}
          >
            <UnfoldLessIcon />
          </IconButton>

Only collapses the last opened folder.

When clicking the button, I want to set the state of ALL opened folders to false not just the last opened one.

Any way to solve this problem?

>Solution :

You could create a "multi-ref" – ref object that stores an array of every rendered Folder component. Then, just iterate over every element and call the closing function.

export default function App() {
  const ref = useRef([]);

  const content = data.map(({ id }, idx) => (
    <Folder key={id} ref={(el) => (ref.current[idx] = el)} />
  ));

  return (
    <div className="App">
      <button
        onClick={() => {
          ref.current.forEach((el) => el.handleClose());
        }}
      >
        Close all
      </button>
      {content}
    </div>
  );
}

Codesandbox: https://codesandbox.io/s/magical-cray-9ylred?file=/src/App.js

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading