I can't seem to figure out how to print child routes in React Router v5. Here is how I have setup my application.
1) index.jsx
ReactDOM.render(
<Provider store={store}>
<IntlProvider defaultLocale="en" locale="en" messages={messages}>
<ThemeProvider theme={theme}>
{Routes()}
</ThemeProvider>
</IntlProvider>
</Provider>,
root,
);
2) Routes.jsx
export default function Routes() {
return (
<ConnectedRouter history={history}>
<Switch>
<Route path="/welcome" component={App} />
<Route component={UnknownPage} />
</Switch>
</ConnectedRouter>
);
}
3) App.jsx
const App = ({ location }) => (
<div>
<DialogMount />
<RefreshSession />
<Masthead />
<Navigation />
<PageWrapper>
<NavTabs location={location} />
<ContentWrapper>
<Alert />
<Switch>
{generateRoutes(routesConfig)}
</Switch>
</ContentWrapper>
</PageWrapper>
</div>
);
4) generateRoutes method
export const generateRoutes = (routes = []) => Object.values(routes).map((route) => {
if (route.redirect) {
return [];
} else if (route.children) {
return (
<Route key={route.path} path={route.path}>
<Switch>
{generateRoutes(route.children)}
</Switch>
</Route>
);
}
return <Route key={route.path} path={route.path} component={route.component} />;
}).reduce((navigation, route) => navigation.concat(route), []);
5) routesConfig
const routesConfig = {
parent: {
path: 'parent',
name: 'parent',
children: {
child1: {
path: 'child1',
name: 'child1',
component: Child1,
},
},
},
};
The problem is, from my App.jsx, everything until the NavTabs is being rendered. Just the routed part of it is not being rendered. I know I am missing something very silly here but can't seem to figure out.
Any help is appreciated.
Edit after Shubham's answer:
I made the changes, but still facing the same issue. However instead of
render={props => <route.component {...props} />}
I used
children={props => <route.component {...props} />}
.
This seems to be loading the components, but now I see errors as such:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Licensing`.
at createFiberFromTypeAndProps (react-dom.development.js:23965)
at createFiberFromElement (react-dom.development.js:23988)
at createChild (react-dom.development.js:13628)
at reconcileChildrenArray (react-dom.development.js:13900)
at reconcileChildFibers (react-dom.development.js:14305)
at reconcileChildren (react-dom.development.js:16762)
at updateHostComponent (react-dom.development.js:17302)
at beginWork (react-dom.development.js:18627)
at HTMLUnknownElement.callCallback (react-dom.development.js:188)
at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
The issue is happening because unless you specify the nested routes within the rendered component itself, you need to provide the entire pathname to it.
The solution is to pass on a prefix to append before the pathname. Also we need a trailing /
const generateRoutes = (routes = [], prefix = "") =>
Object.values(routes)
.map(route => {
console.log(prefix);
if (route.redirect) {
return [];
} else if (route.children) {
return (
<Route key={route.path} path={`${prefix}/${route.path}`}>
<Switch>
{generateRoutes(route.children, prefix + "/" + route.path)}
</Switch>
</Route>
);
}
return (
<Route
path={`${prefix}/${route.path}`}
key={route.path}
render={props => <route.component {...props} />}
/>
);
})
.reduce((navigation, route) => navigation.concat(route), []);