вкладки AntD для использования React-роутера - PullRequest
0 голосов
/ 06 июня 2018

Интересно, есть ли способ, которым мы можем отображать маршруты на основе вложенных маршрутов для каждой вкладки.

Например, когда мы перейдем к

http://localhost:3000/base/a
http://localhost:3000/base/b

Мы ожидаем, что у нас будет base компонент, который обеспечивает вид компоновки и основанный на том, что tab мы щелкаем по нему, должен отобразить nested route компонент.

Приведенный ниже пример работает без использования реакции-маршрутизатора для рендеринга компонента вкладки.

Ниже приведена конфигурация маршрута

<Route path={"/base:scope" } exact={true} { component: BaseComponent } />

НижеКомпонент будет отображать страницу с вкладками

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 >
        );
    }
}

Ожидание:

Мы хотим написать, чтобы быть более специфичным для реагирующего маршрутизатора, например

<Routes path={"/base"} exact={false} component={ComponentBase} />
<Routes path={"/base/a"} exact={true} component={ComponentBase} />
<Routes path={"/base/b"} exact={true} component={ComponentBase} />

Но в этом случае мы не знаем, как отобразить страницу, так как реагирующий маршрутизатор не обрабатывает страницу, поэтому мы замечаем вкладки, но не отображаем содержимое.

Вот модифицированный компонент без содержимого рендеринга, так как мы ожидаем, что Reaction-router выполнит рендеринг компонента.

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 >
        );
    }
}

Ответы [ 2 ]

0 голосов
/ 04 июня 2019

Я попытался создать компонент RoutedTabs, используя вкладки antd.Я добавил документацию для того же.

import React from "react";
import PropTypes from "prop-types";
import { Tabs } from "antd";
import { Switch, Route } from "react-router-dom";

import _each from "lodash/each";
import _map from "lodash/map";
const { TabPane } = Tabs;
/**
 * RoutedTabs is Ant Design based dynamic navigation tabs component.
 * It takes router config as prop and render the component as well as update the window location corrosponding to the tab.
 * Example of routeConfig
 * overview: {
        label: "Overview",
        component: RestaurantOverview,
        getRoute: url => url
    },
    menu: {
        label: "Menu",
        component: Menu,
        getRoute: url => `${url}/menu`
    },
    "menu-holiday-slot": {
        label: "Menu Holiday Slot",
        component: MenuHolidaySlots,
        getRoute: url => `${url}/menu-holiday-slot`
    }
    This will render three tabs Overview, Menu, Menu Holiday Slot and routes based on what getRoute method returns.
 */
const RoutedTabs = props => {
    const { tabsProps, routeConfig } = props;
    const { url, path } = props.match;
    const tabToRouteMap = {};
    const routeToTabsMap = {};
    _each(routeConfig, (configObj, routeKey) => {
        const routeURL = configObj.getRoute(url);
        tabToRouteMap[routeKey] = routeURL;
        routeToTabsMap[routeURL] = routeKey;
    });
    const defaultActiveKey = routeToTabsMap[props.history.location.pathname];
    const tabPaneNodes = _map(routeConfig, (configObj, routeKey) => (
        <TabPane tab={configObj.label} key={routeKey} />
    ));
    const routeNodes = _map(routeConfig, (configObj, routeKey) => (
        <Route
            path={configObj.getRoute(path)}
            exact
            key={routeKey}
            component={configObj.component}
        />
    ));
    const onTabChange = activeKey => {
        props.history.push(tabToRouteMap[activeKey]);
    };
    return (
        <>
            <Tabs {...tabsProps} onChange={onTabChange} defaultActiveKey={defaultActiveKey}>
                {tabPaneNodes}
            </Tabs>
            <Switch>{routeNodes}</Switch>
        </>
    );
};

RoutedTabs.propTypes = {
    tabsProps: PropTypes.object.isRequired, // As per https://ant.design/components/tabs/#Tabs
    routeConfig: PropTypes.object.isRequired,
    match: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
};

export default RoutedTabs;
0 голосов
/ 06 июня 2018

Если вы уверены, что хотите явно определить вкладки с помощью маршрутизатора, тогда вы устанавливаете опору в компоненте:

<Route path={"/base/a"} exact={true} render={() => <ComponentBase tab="a" />} />

Дополнительная информация о маршруте из документов реагирующего маршрутизатора.

Я думаю, что вам было бы лучше использовать props.match.params, предоставляемый реагирующим маршрутизатором, вместо явного определения вкладок, дополнительную информацию и пример здесь .

Вы можете чемполучите значение {props.match.params.base} и перетащите эту вкладку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...