fix: carousel reInit event listener not removed on unmount (memory leak)
Author: josephdscsCreated Jun 9, 2026Updated Sep 8, 2026
Bug
In apps/web/src/components/ui/carousel.tsx (lines 97–106), the useEffect registers two Embla carousel event listeners but the cleanup function only removes one of them:
React.useEffect(() => {
if (!api) return
onSelect(api)
api.on("reInit", onSelect) // registered
api.on("select", onSelect) // registered
return () => {
// api?.off("reInit", onSelect) ← missing
api?.off("select", onSelect)
}
}, [api, onSelect])
The reInit listener is never unsubscribed, causing it to accumulate in memory on each mount/unmount cycle.
Fix
return () => {
api?.off("reInit", onSelect)
api?.off("select", onSelect)
}
Fix is ready on a fork branch: https://github.com/josephdscs/OpenCut/tree/fix/carousel-missing-reinit-cleanup
Source: OpenCut-app/OpenCut