I am trying to utilize nested routes in order to maintain the appearance of a parent component on screen, and as the user navigates left and right in a tab structure, the content in that tabbed interface updates. I do not want the parent component to remount or even re-render, only it's children to change. This is a completely keyboard-based navigation system, so we are not using Links or click events, just hitting left/right/up/down/enter on the keyboard.
Unfortunately, I cannot share my exact code for privacy reasons, but here is the general code structure (obviously not compilable, just to get the gist of what our architecture is like).
in App.js
class App extends Component {
render() {
return (
<div className="App">
<Switch>
<Route
path="/"
exact
match={ true }
component={ () => <MainMenu/> }
/>
<Route
path="/category/:uniqueID"
exact
component={ () => <CategoryComponent childArray=[child1, child2, child3] /> }
/>
/>
</Switch>
</div>
);
}
}
in CategoryComponent.js
class CategoryComponent extends Component {
render() {
var childRoutes;
this.props.childArray.forEach(child => {
childRoutes.push(
<Route
key=child.id
path={ `${this.props.match.path}/${child.path}` }
component={ () => <ChildComponent/> }
/>
);
});
return (
<div className="CategoryComponent">
... // a bunch of UI stuff goes here, including the navigation for the child components
<Switch>
{ childRoutes }
</Switch>
</div>
);
}
}
and finally, in the ChildComponent.js
class ChildComponent extends Component {
shouldComponentUpdate(nextProps) {
// because this navigation is done exclusively by keyboard,
// each child has a property of selected or not that it gets from its parent,
// so only the currently selected one should actually be doing the redirect
if (!this.props.isSelected && nextProps.isSelected) {
this.redirect = true;
}
}
render() {
var redirect;
if (this.redirect) {
redirect =
<Redirect
to={ `${this.props.match.path}/${this.props.thisChildPath}` }
/>;
}
return (
<div className="ChildComponent">
{ redirect }
</div>
);
}
}
Hopefully all of the above made sense, it's as simple as I think I can make it from our crazy complex application. Basically:
- we have an app with a route that utilizes a unique ID, ie. myApp.com/category/1234
- inside of this category, we have some tabs to navigate to, like blue, red, yellow, and for each one, we want to nest the route inside of the above and wind up with something like myApp.com/category/1234/blue, which will update only a part of the screen
The problem I am having is that it seems no matter where I place the redirects, if I use exact or (non-exact paths), or if I use push as true in the Redirect, the parent component ALWAYS remounts. I end up with an entirely new parent component, which will wipe out certain elements saved in local state. The App never remounts, but the Parent Component does. I only want the Child Components to remount, the parent should stay exactly as is. Originally the Category component was even a Higher Order Component, and we switched this to just one normal component class, but with or without conditionally rendering specific cases, didn't seem to make any different either.
Also, I have been playing around with this codesandbox, and adapted the original code to more closely match my project and utilize both links and redirects, and the parent app component never seemed to remount. So...it SEEMS like it's possible, I'm just not sure what I'm doing wrong.
Any help would be greatly appreciated :) thanks!