为什么Framer Motion的动画在组件卸载时会报错?
我在用Framer Motion的useAnimation控制侧边栏动画时,页面跳转后控制台总是报错:Cannot read properties of null (reading 'style')。代码里明明加了清理函数,但问题还是存在。
具体场景是点击关闭按钮后,侧边栏会执行收起动画,动画结束后跳转页面。但有时候跳转速度比动画快,就会报这个错。尝试过在useEffect里加依赖项和手动清除动画队列都没用。
import { useAnimation, motion } from 'framer-motion';
function Sidebar() {
const controls = useAnimation();
const close = () => {
controls.start({ x: '-100%' });
controls.onPlay(() => {
setTimeout(() => window.location.href = '/', 500);
});
};
return (
<motion.div animate={controls}>
<button onClick={close}>关闭</button>
</motion.div>
);
}
错误发生在跳转时,感觉是动画还在执行就被打断了。是不是应该在路由跳转前先等待动画完成?或者需要给动画加个ref来手动清理?
解决办法其实不复杂,你可以用一个标志位来确保动画只在组件挂载时执行。具体来说就是在useEffect里监听组件的挂载状态,然后在动画执行前检查这个状态。
下面是修改后的代码:
这里的关键点有两个:第一是用
isMounted来跟踪组件的挂载状态,防止在组件卸载后还执行跳转逻辑;第二是在动画的then回调里再次检查挂载状态,确保跳转只会在组件还存在时发生。当时我也试过其他方法,比如手动调用
controls.stop()来中断动画,但发现这种方式不够可靠。后来改成这种挂载状态的方案才彻底解决问题。对了,如果你用的是React Router,建议换成
useHistory或useNavigate来做页面跳转,会比直接改window.location更优雅一些。