Next.js 13(App Router)封装Framer Motion为可复用组件的问题
在Next.js服务器组件中复用Framer Motion的正确方案
你之前的写法错误在于:返回motion对象的函数组件无法通过<Motion.div />的方式调用——因为函数组件本身没有div这类静态属性,而motion.div是motion对象的属性,不是组件的属性。
下面提供两种可行的实现方案:
方案1:封装常用的单个动效元素
直接导出motion的具体元素,每个元素都是独立的客户端组件:
"use client"; import { motion } from "framer-motion"; // 按需封装你需要的HTML元素 export const MotionDiv = motion.div; export const MotionButton = motion.button; export const MotionSection = motion.section; export const MotionSpan = motion.span;
在服务器组件中直接导入使用:
import { MotionDiv, MotionButton } from "@/components/MotionElements"; export default function ServerPage() { return ( <div className="container mx-auto p-4"> <MotionDiv initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6 }} className="mb-6" > 服务器组件渲染的动效容器 </MotionDiv> <MotionButton whileHover={{ scale: 1.05, backgroundColor: "#3b82f6" }} whileTap={{ scale: 0.95 }} className="px-6 py-3 bg-blue-500 text-white rounded-lg" > 带交互动效的按钮 </MotionButton> </div> ); }
方案2:通用动态标签组件
如果需要更灵活地支持任意HTML标签,可以封装一个能动态指定标签的客户端组件:
"use client"; import { motion, MotionProps } from "framer-motion"; // 定义组件的类型,支持所有HTML标签和Framer Motion的属性 type MotionGenericProps<T extends keyof JSX.IntrinsicElements> = MotionProps & JSX.IntrinsicElements[T] & { as: T }; export function Motion<T extends keyof JSX.IntrinsicElements>({ as, ...props }: MotionGenericProps<T>) { // 根据传入的as属性获取对应的motion元素 const MotionElement = motion[as]; return <MotionElement {...props} />; }
在服务器组件中使用时,通过as指定标签类型:
import { Motion } from "@/components/Motion"; export default function ServerPage() { return ( <div className="space-y-4"> <Motion as="h1" initial={{ x: -50 }} animate={{ x: 0 }} transition={{ type: "spring", stiffness: 100 }} className="text-2xl font-bold" > 动态标签的动效标题 </Motion> <Motion as="img" src="/example-image.jpg" alt="示例图片" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.3 }} className="w-full h-64 object-cover rounded" /> </div> ); }
两种方案的核心都是:将Framer Motion的元素封装在带"use client"指令的客户端组件中,然后在服务器组件中导入使用——这样既遵守了Next.js App Router的组件规则,又能实现动效的复用。
内容的提问来源于stack exchange,提问作者xtreebug
相关产品推荐
相关产品推荐

