Wondering if there is a way we can render routes based on nested routes for each tab.
For example, when we browse to
http://localhost:3000/base/a
http://localhost:3000/base/b
We expect to have a base
component which provides kind of layout and based on what tab
we click it should render the nested route
component.
The below example works without using react-router for rendering the tab's component.
Below is route config
<Route path={"/base:scope" } exact={true} { component: BaseComponent } />
Below component will render the page with tabs
import { Layout, Tabs, Row, Col } from 'antd';
import { Link, NavLink, Route, Switch } from 'react-router-dom';
export class BaseComponent extends React.Component {
public state = {
collapsed: false,
};
private onCollapse = collapsed => {
this.setState({ collapsed });
}
get tabs() {
const { collaborators, integration, settings, configuration, billing, tokens, referrals } = this.props;
return [
{
key: 'a',
tab: 'a',
component: ComponentA,
path: '/base/a',
},
{
key: 'b',
tab: 'b',
component: ComponentB,
path: '/base/b',
},
];
}
public componentWillReceiveProps(props) {
if (!_.isEqual(_.get(this.props, 'match.url'), _.get(props, 'match.url'))) {
this.setState({ key: _.get(props, 'match.url') });
}
}
public render() {
const { renderer, router } = this.context;
const { onLogOut, match, user, profile } = this.props;
return (
<React.Fragment>
<Header className={renderer.renderRule(styles.header, this.props)}>
<div className={renderer.renderRule(styles.title, this.props)}>
Account Settings
</div>
</Header>
<Content>
<div className={renderer.renderRule(styles.container, this.props)}>
<Tabs
animated={false}
defaultActiveKey={match.url}
onChange={key => router.history.push(key)}
className={`${renderer.renderRule(styles.tabs)}`}
>
{_.map(this.tabs, (record, index) => (
<TabPane
key={record.path}
className={renderer.renderRule(styles.pane)}
tab={<span>{record.tab}</span>}
>
{React.createElement(record.component, null, null)}
</TabPane>
))}
</Tabs>
</div>
</Content>
</React.Fragment >
);
}
}
Expectation:
We want to write to be more react-router specific like
<Routes path={"/base"} exact={false} component={ComponentBase} />
<Routes path={"/base/a"} exact={true} component={ComponentBase} />
<Routes path={"/base/b"} exact={true} component={ComponentBase} />
But in this case we don't know how to render the page as the react-router not rending the page so we notice the tabs but no render content.
Here is the modified component without render content as we expect react-router to render the component.
export class BaseComponent extends React.Component {
public state = {
collapsed: false,
};
private onCollapse = collapsed => {
this.setState({ collapsed });
}
get tabs() {
const { collaborators, integration, settings, configuration, billing, tokens, referrals } = this.props;
return [
{
key: 'a',
tab: 'a',
path: '/base/a',
},
{
key: 'b',
tab: 'b',
path: '/base/b',
},
];
}
public componentWillReceiveProps(props) {
if (!_.isEqual(_.get(this.props, 'match.url'), _.get(props, 'match.url'))) {
this.setState({ key: _.get(props, 'match.url') });
}
}
public render() {
const { renderer, router } = this.context;
const { onLogOut, match, user, profile } = this.props;
return (
<React.Fragment>
<Header className={renderer.renderRule(styles.header, this.props)}>
<div className={renderer.renderRule(styles.title, this.props)}>
Account Settings
</div>
</Header>
<Content>
<div className={renderer.renderRule(styles.container, this.props)}>
<Tabs
animated={false}
defaultActiveKey={match.url}
onChange={key => router.history.push(key)}
className={`${renderer.renderRule(styles.tabs)}`}
>
{_.map(this.tabs, (record, index) => (
<TabPane
key={record.path}
className={renderer.renderRule(styles.pane)}
tab={<span>{record.tab}</span>}
>
</TabPane>
))}
</Tabs>
</div>
</Content>
</React.Fragment >
);
}
}