React Router: перейдите к / compose / tweet, но сохраните ортогональный предыдущий маршрут (например, / уведомления) - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь воссоздать шаблон с помощью React Router. Лучше всего это описать на примере Twitter: когда вы нажимаете кнопку Tweet, браузер переходит на /compose/tweet, монтируя компонент composer. Однако, и это ключ , предыдущий маршрут (/home, /explore, /notifications, /messages) остается подключенным, несмотря на изменение маршрута. Как вы это сделаете?

Это можно назвать двумерной маршрутизацией: маршрут /compose/tweet поддерживается ортогональным по отношению к другим маршрутам, которые отображают основной вид. Другие маршруты скрываются (т. Е. Больше не находятся в адресной строке) при переходе к /compose/tweet, в результате чего сразу отображаются два независимых маршрута (скажем, /notifications и /compose/tweet).

Мой фактический пример: мне нужно показать меню пользовательских настроек (/user/menu) в виде большой боковой панели, но я не хочу, чтобы это изменило, перемещался ли пользователь по / (домашняя страница), /faq, /contact и т. д. c. Исходя из моего текущего понимания React Router, как только вы нажмете /user/menu, любой другой маршрут (например, /faq) будет размонтирован на основе соответствия маршрута.

Кэширование предыдущего маршрута (например, Redux, который я уже широко использую), кажется неосуществимым, поскольку, даже если я смогу перенаправить пользователя на предыдущий маршрут после выхода из /user/menu, React все равно будет размонтировать компоненты, фактически показывая домашнюю страницу в фоновом режиме до тех пор, пока пользователь не выйдет /user/menu и не будет перенаправлен туда, где он находился, что не является предполагаемым поведением. Я бы хотел, чтобы остальная часть страницы оставалась там с визуализированными компонентами, как это делает Твиттер.

Я что-то пропускаю? Это простой шаблон, и я что-то упускаю?

Примечание: это приложение SSR isomorphi c, но я думаю / надеюсь, что это ничего не изменит.

1 Ответ

0 голосов
/ 25 марта 2020

Несмотря на предложение Адама Абрамова оставить React Router в качестве источника истины для всего, что может быть передано в качестве маршрута, и избежать глубоких интеграций между Router и Redux, я обнаружил, что мне нужно использовать Redux в качестве основного источника правды в этом (важно ) вариант использования. Я все еще хотел иметь Route компоненты для целей SSR и SEO.

Итак, я создал свои собственные компоненты MultidimensionalSwitch и MultidimensionalRoute для решения этого варианта использования. Если MultidimensionalSwitch смонтирован, он будет отображать компоненты в их подсузах, но если ни один из них не будет сопоставлен, он будет отображать их на основе другого измерения, которое предоставляется Redux в дополнительном свойстве alt соответствующего MultidimensionalRoute.

Ниже приведен код, не стесняйтесь отвечать / спрашивать, если вам нужна дополнительная информация о нем.

Main

class _Main extends Component {
    render() {
        const {menuOpen,selected} = this.props;
        return (
            <Fragment>
                <Route exact path={exactRoutes.ROOT}      component={() => <Redirect to={selected?exactRoutes[selected]:exactRoutes.HOME} />} />
                <Header />
                <Route       path={nestedRoutes.AUTH+routeParams.LOGIN_SIGNUP.key}      component={ScreenAuth} />
                <Route       path={exactRoutes.USER_MENU}                               component={ScreenUser} />
                {!menuOpen?"":<ScreenMenu />}
                <ScreenMain>
                    <MultidimensionalSwitch>
                        <MultidimensionalRoute path={exactRoutes.HOME}          alt={selected===guestMenuOption.HOME}           component={GuestHome} />
                        <MultidimensionalRoute path={exactRoutes.USER}          alt={selected===guestMenuOption.USER}           component={User} />
                        <MultidimensionalRoute path={exactRoutes.VISION}        alt={selected===guestMenuOption.VISION}         component={GuestVision} />
                        <MultidimensionalRoute path={exactRoutes.FAQ}           alt={selected===guestMenuOption.FAQ}            component={GuestFaq} />
                        <MultidimensionalRoute path={exactRoutes.INFOGRAPHICS}  alt={selected===guestMenuOption.INFOGRAPHICS}   component={GuestInfographics} />
                        <MultidimensionalRoute path={exactRoutes.BLOG}          alt={selected===guestMenuOption.BLOG}           component={GuestBlog} />
                        <MultidimensionalRoute path={exactRoutes.CONTACT}       alt={selected===guestMenuOption.CONTACT}        component={GuestContact} />
                    </MultidimensionalSwitch>
                    <Footer />
                </ScreenMain>
                <Flare />
            </Fragment>
        );
    };
}

const mapStateToProps = state => ({
    menuOpen:           state.client.guest.menuOpen,
    selected:           state.client.guest.guestMenuOption,
});

const Main = withRouter(connect(mapStateToProps,{})(_Main));

export default Main;

Многомерный переключатель

class _MultidimensionalSwitch extends Component {
    render() {
        return (
            <Fragment>
                <Switch>
                    {this.props.children}
                    {this.props.children.map(child => !child.props.alt?"":<Route path={nestedRoutes.ROOT} component={child.props.component} />)}
                </Switch>
            </Fragment>
        );
    }
}

const mapStateToProps = state => ({
    selected:           state.client.guest.guestMenuOption,
});

const MultidimensionalSwitch = withRouter(connect(mapStateToProps,{})(_MultidimensionalSwitch));

export default MultidimensionalSwitch;

Многомерный маршрут

class _MultidimensionalRoute extends Component {
    render() {
        const {path,component} = this.props;
        return (
            <Fragment>
                <Route exact path={path} component={component} />
            </Fragment>
        );
    }
}

const mapStateToProps = (state,ownProps) => ({
    path:               ownProps.path,
    component:          ownProps.component,
});

const MultidimensionalRoute = withRouter(connect(mapStateToProps,{})(_MultidimensionalRoute));

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