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