Redwood: Are layouts re-rendered on each navigation

Created on 15 Mar 2020  路  6Comments  路  Source: redwoodjs/redwood

If two routes share the same layout does that layout re-render, unmount and remount. What's the cost associated with that?

Based off of this tweet:
https://mobile.twitter.com/sebastienlorber/status/1238889193461383169

kindiscussion router

Most helpful comment

@RobertBroersma I really like the approach that react router v6 has taken.

The current implementation in RW Router and the approaches suggest in the docs leaves much to be desired. The current implementation adds extra boilerplate when creating new pages because you have to add the layout to every Page. On each page change components need to be re-rendered. This breaks down if you have an API request in your SideBar component. You end up requesting existing data every page change. An example would be the recommended channels on twitch.tv. Requesting recommended channels anytime you click on a channel from the SideBar would be a nuisance and call for unnecessary API calls. As well as applications that use a modal to display show page content. Examples like new Reddit loads a post in a modal overtop of the feed. Now there are ways to work around this in RW but that seems to break RW patterns even more. Lifting the component you lose all benefits of what the router is providing.

image

I think it is important to note the point of a Layout is to stay the same on each page and React principles would say if state isn't updating then we should not re-render. The only thing that changes is the browser URL to contain additional parameters that are consumed by inner components. I guess what I am trying to get at is I think RW should handle Layouts at one step higher then the Page and agree with the tweet posted above. The Outlet solution works nicely because it allows flexibility and can live along side the current flat structure.

All 6 comments

Hi

The cost is in performance but also more importantly it would mean a layout state would be reset, and that can be annoying

This does happen. A route transition unmounts everything inside the Route, including the Layout. When the next route is mounted, the Layout is mounted again. The same thing happens with other routers (e.g. Reach Router) for example if you only have one level of routing.

I think Redwood Router would need some kind of nested Routes to avoid this issue while playing nice in React lifecycles. So if we wanted these paths and components...

/ -> HomePage
/thing -> ThingHomePage
/thing/inner -> ThingInnerPage

...and we wanted ThingHomePage and ThingInnerPage to share a Layout without unmounting it, I imagine the component hierarchy could be something like

<Router>
  <Route path="/" page={HomePage}" name="home>
  <Route path="/thing" page={ThingLayout}">
    <Route path="/" page={ThingHomePage} name="thing" />    
    <Route path="/inner" page={ThingInnerPage} name="thing-inner" /> 
  </Route>
</Router>

馃憤 for more Rails-like conventions over configuration of the Layout component as a first-class citizen component-type.

Other discussion: https://community.redwoodjs.com/t/layouts-as-a-convention-over-configuration/766/2

Tom, who authored the RW Router, is not too keen on nested routes (per last time we talked) although I don't remember the specifics. But this conversation bring up important concerns regarding the tradeoffs.

@jtoar this could be a good topic to put on the list for future discussion.

Thanks, all!

The way React Router v6 handles nested routes would solve the problem (I think) of (un)mounting layouts while allowing to keep all routes in one file (which I believe was what Tom wanted to achieve, cmiiw): https://reacttraining.com/blog/react-router-v6-pre/#nested-routes-and-layouts

Not entirely sure how their implementation works but I think their API with Outlet's and whatnot would fit Redwood!

@RobertBroersma I really like the approach that react router v6 has taken.

The current implementation in RW Router and the approaches suggest in the docs leaves much to be desired. The current implementation adds extra boilerplate when creating new pages because you have to add the layout to every Page. On each page change components need to be re-rendered. This breaks down if you have an API request in your SideBar component. You end up requesting existing data every page change. An example would be the recommended channels on twitch.tv. Requesting recommended channels anytime you click on a channel from the SideBar would be a nuisance and call for unnecessary API calls. As well as applications that use a modal to display show page content. Examples like new Reddit loads a post in a modal overtop of the feed. Now there are ways to work around this in RW but that seems to break RW patterns even more. Lifting the component you lose all benefits of what the router is providing.

image

I think it is important to note the point of a Layout is to stay the same on each page and React principles would say if state isn't updating then we should not re-render. The only thing that changes is the browser URL to contain additional parameters that are consumed by inner components. I guess what I am trying to get at is I think RW should handle Layouts at one step higher then the Page and agree with the tweet posted above. The Outlet solution works nicely because it allows flexibility and can live along side the current flat structure.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thedavidprice picture thedavidprice  路  3Comments

cannikin picture cannikin  路  3Comments

thedavidprice picture thedavidprice  路  3Comments

Tobbe picture Tobbe  路  4Comments

freddydumont picture freddydumont  路  3Comments