Reactjs 保持物料UI选项卡和反应路由器同步

Reactjs 保持物料UI选项卡和反应路由器同步,reactjs,react-router,material-ui,Reactjs,React Router,Material Ui,是否有一种非黑客的方式来保持材料用户界面标签和路由器同步 基本上,我想在用户单击选项卡[1]时更改URL,当用户使用非选项卡链接或按钮导航到不同的页面时,选项卡应该自动更改,当然还有直接访问[2]和页面刷新 另外,如果react路由器的非精确功能也可以,那么/foo选项卡应该在/foo和/foo/bar/1中都处于活动状态 [1] 其他答案建议直接使用历史api,这是react路由器的良好实践吗 [2] 我不知道它叫什么,我的意思是当用户直接加载例如/foo时,而不是加载/code>,然后通过选

是否有一种非黑客的方式来保持材料用户界面标签和路由器同步

基本上,我想在用户单击选项卡[1]时更改URL,当用户使用非选项卡链接或按钮导航到不同的页面时,选项卡应该自动更改,当然还有直接访问[2]和页面刷新

另外,如果react路由器的非精确功能也可以,那么
/foo
选项卡应该在
/foo
/foo/bar/1
中都处于活动状态

[1] 其他答案建议直接使用历史api,这是react路由器的良好实践吗

[2] 我不知道它叫什么,我的意思是当用户直接加载例如
/foo
时,而不是加载
/code>,然后通过选项卡或链接导航到
/foo


编辑:

我创建了一个包装器组件来完成这项工作,但有几个问题:

class CustomTabs extends React.PureComponent {
    constructor() {
        super();

        this.state = {
            activeTab: 0
        }
    }

    setActiveTab(id) {
        this.setState({
            activeTab: id
        });
        return null;
    }

    render() {
        return (
            <div>
                {this.props.children.map((tab,index) => {
                    return (
                        <Route
                            key={index}
                            path={tab.props.path||"/"}
                            exact={tab.props.exact||false}
                            render={() => this.setActiveTab(index)}
                        />
                    );
                })}
                <Tabs
                    style={{height: '64px'}}
                    contentContainerStyle={{height: '100%'}}
                    tabItemContainerStyle={{height: '100%'}}
                    value={this.state.activeTab}
                >
                    {this.props.children.map((tab,index) => {
                        return (
                            <Tab
                                key={index}
                                value={index}
                                label={tab.props.label||""}
                                style={{paddingLeft: '10px', paddingRight: '10px', height: '64px'}}
                                onActive={() => {
                                    this.props.history.push(tab.props.path||"/")
                                }}
                            />
                        );
                    })}
                </Tabs>
            </div>
        );
    }
}

您可以使用NavLink组件

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

<NavLink
  activeClassName="active"
  to="/foo"
>Tab 1</NavLink>
从'react router dom'导入{NavLink};
表1
当/foo是路由时,
active
类将添加到此链接
NavLink
还有一个
isActive
道具,可以通过该道具传递一个函数来进一步自定义确定链接是否处于活动状态的功能


首先,感谢您回答您的问题。 我以不同的方式处理这个问题,我决定在这里发表文章,以供社区欣赏

我在这里的理由是:“如果我能告诉Tabs组件哪个是活动的,那就简单多了。”

实现这一点非常简单,可以通过为Tabs组件设置一个已知的固定值并将该值分配给任何应该处于活动状态的tab来实现

此解决方案要求承载选项卡的组件可以从react router访问道具,例如位置和匹配,如下所示


首先,我们创建一个函数factory,从render方法中删除臃肿的代码。如果所需的路由匹配,则将固定的Tabs值设置为Tab,另一方面,我只是抛出一个任意常量,例如无穷大


const mountTabValueFactory=(位置,选项卡ID)=>(路由)=>!!匹配路径(location.pathname,{path:route,exact:true})?塔比德:无限你能发布你的小代码片段来更清楚地理解你的问题吗?这行不通。检查此项:
选项卡
组件由父级
选项卡
管理,活动选项卡通过更改其
属性进行更改。
class CustomTabsImpl extends PureComponent {
    constructor() {
        super();

        this.state = {
            activeTab: 0
        }
    }

    componentWillMount() {
        this.state.activeTab = this.pathToTab(); // eslint-disable-line react/no-direct-mutation-state
    }

    componentWillUpdate() {
        setTimeout(() => {
            let newTab = this.pathToTab();
            this.setState({
                activeTab: newTab
            });
        }, 1);
    }

    pathToTab() {
        let newTab = 0;

        this.props.children.forEach((tab,index) => {
            let match = matchPath(this.props.location.pathname, {
                path: tab.props.path || "/",
                exact: tab.props.exact || false
            });
            if(match) {
                newTab = index;
            }
        });

        return newTab;
    }

    changeHandler(id, event, tab) {
        this.props.history.push(tab.props['data-path'] || "/");
        this.setState({
            activeTab: id
        });
    }

    render() {
        return (
            <div>
                <Tabs
                    style={{height: '64px'}}
                    contentContainerStyle={{height: '100%'}}
                    tabItemContainerStyle={{height: '100%'}}
                    onChange={(id,event,tab) => this.changeHandler(id,event,tab)}
                    value={this.state.activeTab}
                >
                    {this.props.children.map((tab,index) => {
                        return (
                            <Tab
                                key={index}
                                value={index}
                                label={tab.props.label||""}
                                data-path={tab.props.path||"/"}
                                style={{height: '64px', width: '100px'}}
                            />
                        );
                    })}
                </Tabs>
            </div>
        );
    }
}

const CustomTabs = withRouter(CustomTabsImpl);
import { NavLink } from 'react-router-dom';

<NavLink
  activeClassName="active"
  to="/foo"
>Tab 1</NavLink>