Skip to content

Instantly share code, notes, and snippets.

@cladley
Created April 26, 2019 10:35
Show Gist options
  • Save cladley/052e89134dff03529c122670a0e2616a to your computer and use it in GitHub Desktop.
Save cladley/052e89134dff03529c122670a0e2616a to your computer and use it in GitHub Desktop.
Accordion using react hooks
import React, {forwardRef, useRef, useImperativeHandle, useState, useCallback, useMemo} from 'react';
const Accordion = (props) => {
let items = useRef(new Map()).current;
const handleOnToggle = (id) => {
items.forEach((value, key) => {
if (key != id) {
value.close();
}
});
};
const registerNode = useCallback((node) => {
if (node) {
items.set(node.id, node);
}
}, []);
return (
React.Children.map(props.children, child => {
return React.cloneElement(child, {
ref: registerNode,
onToggle: handleOnToggle
});
})
);
};
const Item = forwardRef((props, ref) => {
const [isOpen, setIsOpen] = useState(false);
const id = useMemo(() => (String(Math.random())), []);
const toggle = () => {
setIsOpen(o => !o);
props.onToggle(id);
};
useImperativeHandle(ref, () => {
return {
id: id,
close() {
setIsOpen(false);
}
};
});
return (
<div>
<h5 onClick={toggle}>{props.title}</h5>
{isOpen && <div>
{props.children}
</div>}
</div>
);
});
Accordion.Item = Item;
export default Accordion;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment