Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EXPERIMENTAL] Route enter/exit transitions with Glue Component. #56591

Open
wants to merge 2 commits into
base: canary
Choose a base branch
from

Conversation

evankirkiles
Copy link

@evankirkiles evankirkiles commented Oct 8, 2023

Discussion

#56594

What?

A persisted, opt-in, user-provided glue client component which slots between a layout and a template, actually receiving the keyed templates as a child, unlike layout. This allows enter and exit transitions like framer-motion provides:

Screen.Recording.2023-10-08.at.3.05.00.PM.mov

See examples/with-framer-motion-app-dir in this branch for the app code for the above.

EDIT: AnimatePresence does seem to break in this case when route transitions happen too quickly, i.e. you navigate elsewhere while a route is still transitioning out. In this case, nothing shows up (with "wait" mode) or both routes render together (with "sync" mode). I'm not sure why, haven't dug into the interaction between Next' router and FramerMotion yet. Waiting for exit to navigate does work consistently, at least.

Why?

Route exit transitions are long overdue for Next.js 13's appDir. I think I speak for a lot of web designers and developers when I say this is a major factor preventing migration from pages/ to app/.

How?

Closes NEXT-
Fixes #49596

@evankirkiles
Copy link
Author

PR also related to #49279 , a thread in which there's a (apparently now broken) hack that takes the userland approach of reading, freezing in a ref, and then re-providing the entire LayoutRouterContext to stagger it enough for an exit transition to run.

@clieee
Copy link

clieee commented Nov 16, 2023

Still no updates on this?

@evankirkiles
Copy link
Author

evankirkiles commented Nov 18, 2023

Taking this out of draft mode and fixing the merge conflicts to hopefully get some more visibility. Regardless of the current quirks with FramerMotion's internal state and the keys of parallel routes' templates, I strongly believe that a feature to actually access template keys should be added under an experimental flag. Devs' hands are tied when it comes to appDir route exit transitions—being able to access the template keys would at least open the door for a solution, be that FramerMotion's <AnimatePresence /> or a more Next.js tailored approach.

I'll just add that route transitions are super important, seen with a few of the other big frameworks:

We're kind of the odd one out. Would love some input from the Next.js team on thoughts / concerns.

@evankirkiles evankirkiles force-pushed the experimental/page-exit-transitions branch from c056d8e to dbba963 Compare November 18, 2023 19:46
@ijjk ijjk added the examples Issue/PR related to examples label Nov 18, 2023
@evankirkiles evankirkiles marked this pull request as ready for review November 18, 2023 19:48
@evankirkiles evankirkiles requested review from manovotny and delbaoliveira and removed request for a team November 18, 2023 19:48
@joebentaylor1995
Copy link

So has this been approved? What's the latest update?

@Cybearnaut
Copy link

Any update on this? really need this common feature on Next, which has been discussed for > 1 year

@liangsu1210
Copy link

Still has this same issue with the latest version, tried to bypass it by frozenroute, but some of the page failed loading, please help

`"use client";

import { useContext, useRef, ReactNode } from "react";
import { LayoutRouterContext } from "next/dist/shared/lib/app-router-context.shared-runtime";

export default function FrozenRoute(props: { children: React.ReactNode }) {
const context = useContext(LayoutRouterContext);
const frozen = useRef(context).current;

return (
<LayoutRouterContext.Provider value={frozen}>
{props.children}
</LayoutRouterContext.Provider>
);
}`

@evankirkiles
Copy link
Author

evankirkiles commented Feb 27, 2024

Just an update for everyone: I'm working on rebasing this PR to the latest canary version and fixing the synchronization issues that are making this existing implementation buggy, as I believe better erroring on newer Next.js versions catch some of the underlying issues that exist with framer-motion's route persisting.

I don't think framer-motion will play nicely out of the box with server components so I've built a small barebones implementation of a Suspense-enabled route persister like framer's AnimatePresence. I've gotten to the point where the first, uncached route transition works, but no route transitions after that work—an issue with an incorrect patch from the server based on the old cacheKey for the transitioning segment when a route is persisted past its lifetime. After that first transition, the segment is always updated with the tree pre-transition—despite the fact that the new tree is correctly requested / returned from the server. It's as if the old route being present past its lifetime is forcing Next to roll back any updates.

Screen.Recording.2024-02-27.at.4.22.15.PM.mov

Notice how navigate is taking us to the correct URL, but the server-patch and RENDER_SYNC reducers roll the state of the tree back to the route pre-transition. The URL shows the desired location, it's just Next's rendering of the page which shows an out-of-date segment.

It's slow progress due to my lack of prior experience and understanding of the internals of RSCs and how server responses patch-update, but I think this PR will ultimately mean an additional change to cacheKey update timing beyond adding in this Glue component. Will report on more progress soon.

Addendum

I'm also curious how Offscreen (now called Activity after React's v19 blog post) will play into this workflow. Having multiple preservedSegments with togglable isActive state will not only give a more native implementation where route persisting can take place, it'll allow the waterfall of patch requests to occur while the previous route is transitioning out—currently, we can only fetch the contents of the new segment once it actually mounts after the transition ends.

@bdrtsky
Copy link

bdrtsky commented Apr 7, 2024

Why this ignored, can we finally fix exit transitions, please 🥲

@tekigg
Copy link

tekigg commented Jun 16, 2024

This soon, please.

it is kind of a must since there's almost no way to do this without freezing the router. Big upvote.

@evankirkiles evankirkiles force-pushed the experimental/page-exit-transitions branch from c09840a to 9df1d30 Compare July 8, 2024 04:19
@ijjk
Copy link
Member

ijjk commented Jul 8, 2024

Allow CI Workflow Run

  • approve CI run for commit: 9df1d30

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
examples Issue/PR related to examples type: next
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Next13.4 appDir does not render layout and template in the way the docs say it should