Проблема с маршрутизацией на маршрутизаторе ReactionJS 4 и Redux - PullRequest
0 голосов
/ 06 октября 2018

Здравствуйте, я создаю проект, в котором я использовалactjs redux и response-router-dom.

По какой-то странной причине, которую я не могу понять, когда я перехожу к http://localhost:3000, я получаюследующая ошибка: Warning: You tried to redirect to the same route you're currently on: "/signin"

Я пробовал много вещей из похожих вопросов, но безуспешно.Возможно Switch не работает?или мне нужна свежая пара глаз, потому что это может быть очевидно ...

Ниже приведен мой исходный код:

router.jsx

import React from 'react';
import { connect } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import Routes from '../routes/index.jsx';

// Global Components
import CustomNavbar from '../navbar/index.jsx';
import Sidemenu from '../sidemenu/index.jsx';
import Emulator from '../emulator/index.jsx';

// Styles
import 'font-awesome/css/font-awesome.css';
import 'bootstrap/dist/css/bootstrap.css';
import '../../sass/style.scss';
import '../../sass/router.scss';

class CustomRouter extends React.Component {

    constructor(props) {
        super(props);
    }

    isSignedin = () => {
        return this.props.user.authenticated;
    }

    isSidemenuOpen = () => {
        return this.props.app.sidemenu.open;
    }

    isEmulatorOpen = () => {
        return this.props.app.emulator.open;
    }

    getWrapperClassName = () => {

        let classList = [];

        if (this.isSignedin()) {
            classList.push('authenticated');
        }

        if (this.isSidemenuOpen()) {
            classList.push('sidemenu');
        }

        if (this.isEmulatorOpen()) {
            classList.push('emulator');
        }

        return classList.join(' ');

    }

    render = () => {

        return (
            <BrowserRouter>

                <div id='wrapper' className={this.getWrapperClassName()}>

                    {(() => {

                        if (this.isSignedin()) {

                            return (
                                <React.Fragment>
                                    <Sidemenu />
                                    <CustomNavbar />
                                    <Emulator />
                                </React.Fragment>
                            )

                        } else {
                            return null;
                        }

                    })()}

                    <div id='page-content'>
                        <div className='p-4'>
                            <Routes />
                        </div>
                    </div>

                </div>

            </BrowserRouter>
        )

    }

}

const mapStateToProps = (state) => {
    return {
        app: state.appReducer,
        user: state.userReducer
    }
}

export default connect(mapStateToProps, null, null, { withRef: true })(CustomRouter);

rout.jsx

import React from 'react';
import { withRouter, Switch, Route } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import AuthenticatedRoute from '../authenticatedRoute/index.jsx';
import UnauthenticatedRoute from '../unauthenticatedRoute/index.jsx';

// Root Components
import Home from '../routes/home/index.jsx';
import Dashboard from '../routes/dashboard/index.jsx';
import Bots from '../routes/bots/index.jsx';
import Actions from '../routes/actions/index.jsx';
import Flows from '../routes/flows/index.jsx';
import Sessions from '../routes/sessions/index.jsx';
import Users from '../routes/users/index.jsx';
import Signin from '../routes/signin/index.jsx';
import Signup from '../routes/signup/index.jsx';
import Reset from '../routes/reset/index.jsx';
import NotFound from '../routes/notfound/index.jsx';

const Routes = ({ location }) => {
    return (
        <TransitionGroup className='transition-group'>
            <CSSTransition key={location.key} classNames='fade' timeout={{ enter: 300, exit: 300 }}>
                <section className='route-group'>
                    <Switch location={location} >
                        <Route path='/' component={Home} exact={true}></Route>
                        <UnauthenticatedRoute path='/signin' component={Signin} exact={true}></UnauthenticatedRoute>
                        <UnauthenticatedRoute path='/signup' component={Signup} exact={true}></UnauthenticatedRoute>
                        <UnauthenticatedRoute path='/reset' component={Reset} exact={true}></UnauthenticatedRoute>
                        {/* <AuthenticatedRoute path='/dashboard' component={Dashboard} exact={true}></AuthenticatedRoute>
                        <AuthenticatedRoute path='/bots/:botId?' component={Bots} exact={true}></AuthenticatedRoute>
                        <AuthenticatedRoute path='/actions/:actionId?' component={Actions} exact={true}></AuthenticatedRoute>
                        <AuthenticatedRoute path='/flows/:flowId?' component={Flows} exact={true}></AuthenticatedRoute>
                        <AuthenticatedRoute path='/users/:userId?' component={Users} exact={true}></AuthenticatedRoute>
                        <AuthenticatedRoute path='/sessions/:sessionId?' component={Sessions} exact={true}></AuthenticatedRoute> */}
                        <Route path='*' component={NotFound}></Route>
                    </Switch>
                </section>
            </CSSTransition>
        </TransitionGroup>
    )
}

export default withRouter(Routes);

home.jsx (/ фиктивный компонент маршрута)

он используется только для перенаправления вас на / панель мониторинга или / входа в систему соответственно

import React from 'react';
import { connect } from 'react-redux';
import { Redirect } from "react-router-dom";

import '../../../sass/home.scss';

class Home extends React.Component {

    constructor(props) {

        super(props);

        this.state = this.getInitialState();

    }

    getInitialState = () => {
        return {};
    }

    render = () => {

        let { authenticated } = this.props.user;

        if (authenticated) {
            console.log('Redirecting to "/dashboard" from home');
            return (
                <Redirect to="/dashboard" />
            )

        } else {
            console.log('Redirecting to "/signin" from home');
            return (
                <Redirect to="/signin" />
            )

        }

    }
}

const mapStateToProps = (state) => {
    return {
        app: state.appReducer,
        user: state.userReducer
    }
}

const mapDispatchToProps = (dispatch) => {
    return {}
}

export default connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(Home);

unauthenticated.jsx

(для маршрутов, которые доступны только без проверки подлинности)

import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect, withRouter } from 'react-router-dom';

class UnauthenticatedRoute extends React.Component {

    constructor(props) {
        super(props);
    }


    isSignedin = () => {
        return this.props.user.authenticated;
    }

    render = () => {

        let { component: Component, ...rest } = this.props;

        console.log('Unauthenticated:', !this.isSignedin() ? `Rendering` : `Redirecting`);

        return (

            <Route {...rest} render={(props) => (
                !this.isSignedin() ? (
                    <Component {...props} />
                ) : (
                        <Redirect to='/dashboard' />
                    )
            )} />

        )

    }

}

const mapStateToProps = (state) => {
    return {
        app: state.appReducer,
        user: state.userReducer
    }
}

const mapDispatchToProps = (dispatch) => {
    return {}
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(UnauthenticatedRoute));

authenticated.jsx

(для маршрутов, которые доступны только при аутентификации)

import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect, withRouter } from 'react-router-dom';

class AuthenticatedRoute extends React.Component {

    constructor(props) {
        super(props);
    }

    isSignedin = () => {
        return this.props.user.authenticated;
    }

    render = () => {

        let { component: Component, ...rest } = this.props;

        console.log('Authenticated:', this.isSignedin() ? `Rendering` : `Redirecting`);

        return (

            <Route {...rest} render={(props) => (
                this.isSignedin() ? (
                    <Component {...props} />
                ) : (
                        <Redirect to='/signin' />
                    )
            )} />

        )

    }

}

const mapStateToProps = (state) => {
    return {
        app: state.appReducer,
        user: state.userReducer
    }
}

const mapDispatchToProps = (dispatch) => {
    return {}
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(AuthenticatedRoute));

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Решение было следующим, и насколько я могу судить, это был вопрос логики. Не было нескольких монтируемых компонентов, если вам интересно.Это было связано с компонентом AuthenticatedRoute & UnauthenticatedRoute.Также я полностью удалил home компонент.

Метод рендеринга с аутентификацией

render = () => {

    let { component: Component, ...rest } = this.props;

    return (

        <Route {...rest} render={(props) => (
            this.isSignedin() ? (
                <Component {...props} />
            ) : (
                    props.location.pathname === '/signin' ? (null) : (<Redirect to='/signin' />)
                )
        )} />

    )

}

Метод рендеринга без аутентификации

render = () => {

    let { component: Component, ...rest } = this.props;

    return (

        <Route {...rest} render={(props) => (
            !this.isSignedin() ? (
                <Component {...props} />
            ) : (
                    props.location.pathname === '/' ? (null) : (<Redirect to='/' />)
                )
        )} />

    )

}
0 голосов
/ 06 октября 2018

Попробуйте упростить и разделить ваши защищенные маршруты на один RequireAuth компонент.С помощью Redux мы можем затем выставить маршруты, когда пользователь прошел аутентификацию.

Возможно, вам удастся обойтись без использования провайдера React Context, но в любом случае вам понадобитсяиспользовать какой-то HOC, который может передать его состояние / методы детям.В противном случае это будет вложенный кошмар состояния HOC и методов, передаваемых туда и обратно.

Рабочий пример: https://codesandbox.io/s/88qmx06082 (реакции-маршрутизатор v3 - одна из причин, почему я использую и предпочитаюv3, потому что это супер легко вкладывать маршруты)

Рабочий пример: https://codesandbox.io/s/yqo75n896x (реакции-маршрутизатор v4)

routs / index.js (v4)

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";
import Home from "../components/Home";
import Header from "../containers/Header";
import Info from "../components/Info";
import Sponsors from "../components/Sponsors";
import Signin from "../containers/Signin";
import RequireAuth from "../containers/RequireAuth";
import rootReducer from "../reducers";

const store = createStore(rootReducer);

export default () => (
  <Provider store={store}>
    <BrowserRouter>
      <div>
        <Header />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/info" component={Info} />
          <Route path="/sponsors" component={Sponsors} />
          <Route path="/protected" component={RequireAuth} />
          <Route path="/signin" component={Signin} />
        </Switch>
      </div>
    </BrowserRouter>
  </Provider>
);

контейнеры / RequireAuth.js (v4)

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";

const RequireAuth = ({ match: { path }, isAuthenticated }) =>
  !isAuthenticated ? (
    <Redirect to="/signin" />
  ) : (
    <div>
      <Route exact path={`${path}/roster`} component={ShowPlayerRoster} />
      <Route path={`${path}/roster/:id`} component={ShowPlayerStats} />
      <Route path={`${path}/schedule`} component={Schedule} />
    </div>
  );

export default connect(state => ({
  isAuthenticated: state.auth.isAuthenticated
}))(RequireAuth);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...