docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

Avoid layout unmount/remount

Open slorber opened this issue 5 years ago • 3 comments

🐛 Bug Report

Most classic D2 sites will use the same layout component on every single page, apart from a few rare exceptions (like a code playground implemented with a custom page).

When navigating from one page to the other, the layout should not unmount/remount unnecessarily.

Currently, when navigating from the home page to the /docs page, the layout unmounts/remounts.

The only case I found where it does not unmount/remount is when navigating from one doc to another.

Avoiding unmounts/remounts when possible is important for 2 reasons:

  • faster transition from one page to another
  • avoid resetting state of the layout

Probably not urgent to work on this, just wanted to backlog it somewhere :)

Useful link: https://www.gatsbyjs.org/packages/gatsby-plugin-layout/

To Reproduce

yarn docusaurus swizzle @docusaurus/theme-classic Navbar

Add this button somewhere in the navbar:

const TestButton = () => {
  const [bool, setBool] = useState(false);
  return (
    <button onClick={() => setBool((b) => !b)}>Toggle me {String(bool)}</button>
  );
};

image

Expected behavior

Navigating should not reset the button state

Actual Behavior

The button state is reset


Edit: this is also a problem for our mobile drawer that may not animate properly on all page transitions, see https://github.com/facebook/docusaurus/discussions/11063#discussioncomment-12763738

slorber avatar Jun 05 '20 16:06 slorber

@slorber Do you think this is ever attainable? FWIW, it seems like a very common problem in SSR sites. Unless we can have RSC or something similar, I don't think it's possible under the current architecture.

Josh-Cena avatar Jan 09 '22 04:01 Josh-Cena

Yes this is achievable.

We need the layout to be declared statically on the route level so that te parent component can read that info and render the layout above the route (directly in docusaurus core)

addRoute({
  layout: "@theme/Layout",
})

And we need a way for pages to declare that layout as well + a way to extract it from pages. Not sure what's the best solution, but maybe:

export const layout = "@theme/Layout";

This is not very different from how the docs sidebar is handled, just one layer above so that it can work when transitioning from one plugin to another.

We also need a way to have no layout.

For example if you want to create a standalone page not rendering the default layout but something unique.

export const layout = undefined

slorber avatar Jan 12 '22 14:01 slorber

Just a note: the mobile sidebar collapses gracefully when navigating between doc pages because the layout doesn't unmount, but when navigating between two non-doc pages it just disappears without the animation

Josh-Cena avatar Apr 06 '22 13:04 Josh-Cena