Skip to content
Advertisement

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:

 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?

Advertisement

Answer

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

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement