vercel / vercel/next.js

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

Open
#49,596 6 comments 76 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

linear: next Linking and Navigating
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Verify canary release
  • I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.4.0: Mon Mar  6 20:59:58 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6020
    Binaries:
      Node: 18.16.0
      npm: 9.5.1
      Yarn: 1.22.19
      pnpm: N/A
    Relevant packages:
      next: 13.4.2-canary.4
      eslint-config-next: 13.4.1
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.0.4
Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Routing (next/router, next/navigation, next/link)

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/wizardly-wing-fj1kod

To Reproduce

Download and run the files in the sandbox (so that you can attach the React Developer Tools)

Note that in the react developer tools, the following component tree is rendered, showing the top Suspense added by the layout.tsx, two Next internal components, and then the Suspense from the template.tsx:
Screenshot 2023-05-10 at 12 21 48

Describe the Bug

The NextJS Documentation on templates in the app-directory router here says that layouts and templates will be rendered as such:

<Layout>
  {/* Note that the template is given a unique key. */}
  <Template key={routeParam}>{children}</Template>
</Layout>

However, in practice we can clearly see that NextJS inserts a component called OuterLayoutRouter between each layout-template pair, separating the layout from the part of the Template framework that receives the unique key promised by the docs.

This means that components that rely on detecting a change of key of their direct child cannot function in the layout-template lifecycle. In practice this leads to issues primarily with animation libraries, such as #49279.

At its core, though, I think the bug here is that the documentation and the behavior do not align with each other.

Expected Behavior

This could be fixed in one of two ways:

  1. The documentation could be updated to remove the claim that the direct child of the Layout will be a value with a unique per-route key, and the documentation could remove the promise that Templates can be used to perform on-enter and on-exit animations. I think this would be a subpar solution but it would restore consistency between the docs and deployed behavior.
  2. The OuterLayoutRouter in layout-router.tsx could be updated so that it receives the layout.tsx component from the app-render loop and embeds that layout in its returned JSX tree, which would allow the layout and template to truly be parent-child. I think this would be preferable but I'm also still wrapping my head around how the new app render loop works so I don't yet know what would might make this difficult.
Which browser are you using? (if relevant)

Chrome but not relevant

How are you deploying your application? (if relevant)

Not relevant

NEXT-1380

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the linked CodeSandbox reproduction and comparing its component tree with the templates documentation. Then read layout-router.tsx and the app-render loop; done means the documented layout/template relationship and the observed rendering behavior are consistent, including the promised route-specific key behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, react
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.