I'm using react-spring to animate the transition of opening and closing an accordion component that reveals some text. Using this example on the documentation I was able to come up with a simpler version that creates a transition for the height and opacity:
function CollapseListItem({ title, text }: CollapseItemType) {
const [isOpen, setIsOpen] = useState(false);
const [ref, { height: viewHeight }] = useMeasure();
const { height, opacity } = useSpring({
from: { height: 0, opacity: 0 },
to: {
height: isOpen ? viewHeight : 0,
opacity: isOpen ? 1 : 0
}
});
const toggleOpen = () => {
setIsOpen(!isOpen);
};
return (
<>
<button onClick={toggleOpen}>
{title} click to {isOpen ? "close" : "open"}
</button>
<animated.div
ref={ref}
style={{
opacity,
height: isOpen ? "auto" : height,
overflow: "hidden"
}}
>
{text}
</animated.div>
</>
);
}
The issue is that the height transition is only being shown when you close the accordion, when you open the accordion the text suddenly appears, but on the code I can't seem to find why it only works on close, I've tried to hardcode some viewHeight
values but I've had no luck.
After checking more examples, I realized that I was putting the ref
on the wrong component, this change solve the issue:
function CollapseListItem({ title, text }: CollapseItemType) {
const [isOpen, setIsOpen] = useState(false);
const [ref, { height: viewHeight }] = useMeasure();
const props = useSpring({
height: isOpen ? viewHeight : 0,
opacity: isOpen ? 1 : 0
});
const toggleOpen = () => {
setIsOpen(!isOpen);
};
return (
<>
<button onClick={toggleOpen}>
{title} click to {isOpen ? "close" : "open"}
</button>
<animated.div
style={{
...props,
overflow: "hidden"
}}
>
<div ref={ref}>{text}</div>
</animated.div>
</>
);
}
Here's the full solution in case anyone is also trying to build an animated accordion / collapse using spring.