I want to set window size when user resize it.
const [windowSize, setWindowsSize] = useState(window.innerWidth);
useEffect(() => {
window.addEventListener("resize", () => {
setWindowsSize(window.innerWidth);
});
return () =>
window.removeEventListener("resize", () =>
setWindowsSize(window.innerWidth)
);
}, []);
but this process totally destroys my constraints on div. When I resize window I can move this div in both directions.
<motion.div
dragConstraints={{left: 0, right: 0}}
initial={{ x: 0 }}
drag="x"
ref={ref}
dragElastic={0.2}
className="flex gap-8"
>
I tried many things, but nothing seems to work.
Any idea what's the problem or how to solve this issue?
I too was facing the same issue and after some research I got to know something that I will share.
In React, when the component's state or props change, it triggers a re-render of the component. If the dragConstraints
value is being calculated based on the component's props or state, and those values aren't changing when the window is resized, then the dragConstraints
won't be updated either.
Now, framer-motion
adjusts the offset using the translate
CSS property. As your window is resized, the relative positioning is changed and hence it is unable to adjust the position as we think it should according to the constraints.
You can get around this bug for the time being by having the component forcefully re-render by defining a key. This would re-render the component and hence updating the dragConstraints
accordingly.
<motion.div
dragConstraints={{left: 0, right: 0}}
initial={{ x: 0 }}
drag="x"
ref={ref}
dragElastic={0.2}
className="flex gap-8"
key={JSON.stringify(windowSize)}
>
</motion.div>
Another method you can try is by having a dummy div
which will guide the constraints for the movable div
. You can achieve this by having a reference of the dummy div
and use it as the dragContraints
for the movable div
(Nesting is necessary).
<div ref={constraintsRef}>
<motion.div
dragConstraints={constraintsRef}
initial={{ x: 0 }}
drag="x"
ref={ref}
dragElastic={0.2}
className="flex gap-8"
>
</motion.div>
</div>
Obviously you need to use useRef()
hook here.
Hope this would solve your concern.