Search code examples
reactjsnext.jsframer-motion

Framer motion render component animation on each route change


I have a component (Navigation) inside a next.js Layout routed by framer-motion, that renders animation every time I change the route. I want to make it render the animation only the first time I go to the /app page. Tried to use useRef of the component, but it wasn't animating at all. Thanks.

So:

  • /app - it renders the animation
  • /app/chats - it renders the animation again

Navigation animation rerender example

Navigation component itself

export const UserNavigation = () => {
return (
    <motion.section
      initial={{ x: -56 }}
      animate={{ x: 0 }}
      transition={{bounce: false}}
      className="h-[100%] w-14 bg-gray-900"
    >
      <div className="flex flex-col gap-4 items-center justify-center mt-2">
        <Link href="/app/chats">
          <button
            className={classNames(
              isChatsPage ? "bg-gray-700" : "hover:bg-gray-700",
              "text-white rounded-lg p-2 transition duration-200"
            )}
          >
            <ChatBubbleBottomCenterTextIcon className="w-6 h-6" />
            <span className="sr-only">Chats</span>
          </button>
        </Link>
      </div>
    </motion.section>
  );
};

Layout

export const UserLayout: FC<{ children: ReactNode }> = ({ children }) => {
  return (
    <main className="h-screen w-screen flex">
      <UserNavigation />
      {children}
    </main>
  );
};

Chats page

export const Chats: NextPage = () => {
  return (
    <UserLayout>
      <motion.section
        initial={{ x: -56 }}
        animate={{ x: 0 }}
        transition={{ bounce: false }}
        className="w-72 h-full bg-gray-800"
      ></motion.section>
    </UserLayout>
  );
};

Solution

  • I had a similar problem a while ago.

    In my case I needed to manage animations on enter and on exit of a route. This post helped me out - https://blog.sethcorker.com/page-transitions-in-react-router-with-framer-motion. The main takeaway was the need to supply a key prop for the Switch child so AnimatePresence (https://www.framer.com/docs/animate-presence/) could reliably do it's thing.

    But based on your example it doesn't look like you need the added complexity of AnimatePresence. If that is the case, you might just need to fiddle with your layout and routing to get what you need. Here's an example that might give you some ideas of things to try - https://codesandbox.io/s/so-73692915-714wdk.

    Preview of the changes at runtime:

    Screen recording