DEV Community

How to get React Router 4 to allow nested components inside of a Switch

Tyler Smith on October 29, 2019

Recently, I was building a site's admin section with React. The admin section used a repeated pattern for its URL structure: /admin/:contentType ...
Collapse
 
dosentmatter profile image
dosentmatter • Edited

There is a code change you can make for some optimization and to type less.

Looking at react-router code, github.com/ReactTraining/react-rou..., you can see they purposely avoid using React.Children.toArray() and use React.Children.forEach() instead because toArray() actually returns children with keys prefixed. The reason they do that is to preserve your statically defined Routes that probably don't have a key set on them. It is a minor optimization to prevent re-mounting for different Routes that have the same component.

So if we wanted to preserve this functionality, and not have to inject any keys, how should we write our code?

This is how your current code transpiles:

<Switch>
  {AdminRouteGroup({ contentType: "pages" })}
  {AdminRouteGroup({ contentType: "posts" })}
</Switch>
// transpiles to
React.createElement(
  Switch,
  null,
  AdminRouteGroup({ contentType: "pages" }),
  AdminRouteGroup({ contentType: "pages" }),
)
Enter fullscreen mode Exit fullscreen mode

React dev mode sees that those two AdminRouteGroup children are arrays and gives you a warning if they are missing key.

Instead, you can spread the children out. It would be as if you typed JSX out statically and React dev mode won't complain. In general, don't do this. The warning is there for a reason. But you can do this if you know what you are doing and know that the children are stable and won't be reorganized or modified in a render update. See Dan Abramov's comment here:
github.com/facebook/react/issues/1....

React.createElement(
  Switch,
  null,
  ...AdminRouteGroup({ contentType: "pages" }),
  ...AdminRouteGroup({ contentType: "pages" }),
)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jacobsfletch profile image
Jacob Fletcher

I signed up for dev.to only so that I could like this post and send this comment. I needed to map over an array and return a set of routes which does not work because of the nested Fragment within the Switch. This is a verified workaround. Thank you greatly for taking the time to write this up!

Collapse
 
tylerlwsmith profile image
Tyler Smith

Thank you for the kind words! I'm glad you found it useful: this problem had me completely stumped for hours.

Collapse
 
lam1051999 profile image
lam1051999

wow, i had the trouble with nested Fragment in Switch, your answer really really helped me. Thank you so much

Collapse
 
tylerlwsmith profile image
Tyler Smith

I'm glad it helped!

Collapse
 
lupi410 profile image
LV4

This made my day, thanks!

Collapse
 
tylerlwsmith profile image
Tyler Smith

I'm glad this helped! I got stuck on this problem for hours.

Collapse
 
shulashulamit profile image
Shula

Signed up for this website to upvote your post. A clean and easy solution.