Skip to content Skip to sidebar Skip to footer

Should I Use React-router For A Tabs Component?

I'm looking to build a tabs component, where some of the tabs will contain dynamic content. I originally started to follow this tutorial: Creating a tabs component with React Afte

Solution 1:

Yes, this is a perfect job for React Router because it focuses on simplifying the URL redirection process for Single Page Apps.

The use case of tabs for navigation, definitely falls under the scope of React Router. You can use React Router 3 or 4 for this, but the React Router 4 API is on the horizon and the documentation is looking great.

You can find a helpful example on the link above that shows how easy it is to link with tabs. And here is an example that discusses how you can create tabs with custom links.

One of the "gotchas" though that you may want to consider, is that there has been some difficulty restoring the scroll position if you navigate to a different route and then navigate back to the previous route. Here is a thread that discusses this issue further: https://github.com/ReactTraining/react-router/issues/1686.

If restoring scroll position is very important to you, then at this point React Router may not be the best fit for tabs.

Update:

React router v4 has been released, the issue above has been resolved, and now the docs have a guide on how to restore scroll position!

Solution 2:

I had a lot of issues setting this up (Nov 20, 2017) and thought I'd post the final setup here for posterity. I'm using react-router-dom 4.2.2 and material-ui 0.19.4. Bascially, you want to change the hash (#) when the user clicks tabs, and use the hash to find which tab to display. It works pretty well, but unfortunately it adds a tiny bit of a delay, not sure why and will update if I figure it out.

import React, { Component } from 'react';
import { Tabs, Tab } from 'material-ui/Tabs';

export default classTabsComponentextendsComponent{
    constructor(props) {
        super(props);
        this.onActive = this.onActive.bind(this);
        this.getDefaultActiveTab = this.getDefaultActiveTab.bind(this);

        this.tabIndices = {
            '#firsttab': 0,
            '#secondtab': 1
        };
    }
    onActive(tab) {
        const tabName = tab.props.label.toLowerCase();
        this.props.history.replace(`#${tabName}`); // https://reacttraining.com/react-router/web/api/history
    }
    getDefaultActiveTab() {
        const hash = this.props.location.hash;
        returnthis.tabIndices[hash];
    }
    render() {
        return (
            <Tabs
                initialSelectedIndex={this.getDefaultActiveTab()}
            >
                <Tab
                    label="FirstTab"
                    onActive={this.onActive}
                >
                   // ...
                </Tab>
                <Tab
                    label="SecondTab"
                    onActive={this.onActive}
                >
                   // ...
                </Tab>
            </Tabs>
        );
    }
}

And... material-ui ^1.0.0-beta.26

importReact, { Component } from'react';

importTabs, { Tab } from'material-ui/Tabs';
importPaperfrom'material-ui/Paper';

import { withRouter } from'react-router-dom';

importResourcesfrom'../resources/index.jsx';
import styled from'styled-components';

constStyledTabs = styled(Tabs) `
margin:5px;
`;

classLinkableTabsextendsComponent {
    constructor(props) {
        super(props);
        this.getDefaultActiveTab = this.getDefaultActiveTab.bind(this);
        this.switchTab = this.switchTab.bind(this);

        this.state = {
            activeTabIndex: this.getDefaultActiveTab()
        }
    }
    getDefaultActiveTab() {
        const hash = this.props.location.hash;

        let initTabIndex = 0;
        this.props.tabs.forEach((x, i) => {
            const label = x.label;
            if (`#${label.toLowerCase()}` === hash) initTabIndex = i;
        });

        return initTabIndex;
    }

    switchTab(event, activeTabIndex) {
        this.setState({ activeTabIndex });

        //make shareable - modify URLconst tabName = this.props.tabs[activeTabIndex].label.toLowerCase();
        this.props.history.replace(`#${tabName}`);
    }
    render() {
        const { match, location, history, staticContext, ...nonrouterProps } = this.props; //https://github.com/DefinitelyTyped/DefinitelyTyped/issues/13689#issuecomment-296246134const isScrollable = this.props.tabs.length > 2;
        return (
            <div><Paper><StyledTabsfullWidthcenteredscrollable={isScrollable}onChange={this.switchTab}value={this.state.activeTabIndex}
                        {...nonrouterProps}
                    >
                        {
                            this.props.tabs.map(x => <Tabkey={x.label}label={x.label} />)
                        }
                    </StyledTabs></Paper>
                {
                    this.props.tabs[this.state.activeTabIndex].component
                }
            </div>
        );
    }
}

exportdefaultwithRouter(LinkableTabs);

Post a Comment for "Should I Use React-router For A Tabs Component?"