Невозможно получить доступ к компоненту приложения при использовании React Router - PullRequest
3 голосов
/ 08 октября 2019

Я пытаюсь сделать свое приложение более управляемым по маршруту. Я использую React Router и внешний файл маршрутов, чтобы абстрагировать логику маршрута от моих компонентов. Другие маршруты и компоненты работают правильно, за исключением самого компонента App. По сути, я пытаюсь обернуть все другие маршруты в корневой маршрут ('/'), чей компонент - App.js.

Ниже мой routes/index.js файл.

import React from "react";
import PropTypes from "prop-types";
import { Router, Route, Redirect  } from "react-router";

import App from "../App.js";
import Home from "../components/Home/Home";
import Games from "../components/Games/containers/Games";
import LoginSignUp from "../components/LoginSignUp/LoginSignUp";
import NotFound from "../components/NotFound/NotFound";
import Account from "../components/Account/Account";
import Trivia from "../components/Trivia/Trivia";
import store from '../config/store';

const getGame = (nextState, replace, callback) => {
    var userGames = store.getState().auth.user.games;
    if (userGames.includes(parseInt(nextState.match.params.id))){
        return <Trivia/>
    } else {
        return <Redirect to="/404"/>
   }
};

const Routes = ({ history, store }) => {

    return (
         <Router history={history} store={store}>
            <Route path="/" component={App}>
                <Route exact path="/404" component={NotFound} />
                <Route exact path="/give/different/path" component={Home}/>
                <Route exact path="/games" component={Games}/>
                <Route path="/account" component={Account}/>
                <Route path="/games/:id" render={getGame}/>
                <Route path='/login' component={LoginSignUp}/>
            </Route>
        </Router>
    );
};

Routes.propTypes = {
    history: PropTypes.object.isRequired,
    store: PropTypes.object.isRequired
};

export default Routes;

Я также пробовал эту настройку маршрута без <Route exact path="/" component={Home}/>, и я пытался использовать <Route exact path="/" component={App}> безрезультатно.

Ниже приведен мой App.js компонент.

import React from 'react';
import Header from './components/Header/Header.js';
import './App.css';
import {createAction} from "redux-actions";
import {connect} from "react-redux";

class App extends React.Component {

    state = {
        loggedIn: true
    }

    render(){
         debugger
         return (
             <div className="App">
                 <Header loggedIn={this.state.loggedIn} user={this.props.user}/>
             </div>
         );
     }
 }

 const mapStateToProps = ({games, auth}) => {
    return{
        user: auth.user,
        games: games.games
    }
 };

 const mapDispatchToProps = dispatch => {
    return {
        getGame(obj) {
            const actionCreator = createAction(
                "games/getGame"
            );
            const action = actionCreator(obj);
            dispatch(action);
        }
    }
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(App);

Вот мои родственные зависимости и их версии.

"react-router": "^5.1.2",
"react-router-dom": "^5.1.0",
"react-router-redux": "^4.0.8",

Ответы [ 3 ]

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

Я думаю, вы должны изменить свой код таким образом. А также проверьте путь к компоненту приложения при импорте

<Router history={history} store={store}>
  <Switch>
    <Route path="/" component={App} />
    <Route exact path="/404" component={NotFound} />
    <Route exact path="/home" component={Home} />
    <Route exact path="/games" component={Games} />
    <Route path="/account" component={Account} />
    <Route path="/games/:id" render={getGame} />
    <Route path="/login" component={LoginSignUp} />
  </Switch>
</Router>;
0 голосов
/ 09 октября 2019

Благодаря пониманию, предоставленному другими ответами, я смог найти решение, которое удовлетворит все мои потребности.

Вот мои обновленные файлы. Первый - мой корневой index файл. В качестве меры предосторожности я заменил все экземпляры import {Router} from 'react-router' на import {BrowserRouter as Router} from 'react-router-dom', что было предложено ответом на этот вопрос . Замена всех экземпляров react-router на react-router-dom помогла остановить ошибки You should not use <Switch> outside a <Router> или You should not use <Route> outside a <Router>.

    <Provider store={store}>
        <Router history={browserHistory} store={store}>
            <App/>
        </Router>
    </Provider>

Мои маршруты / индекс.

const Routes = ({ history, store }) => {

    return (
            <Switch>
                <Route exact path="/" component={Home} />
                <Route exact path="/404" component={NotFound} />
                <Route exact path="/games" component={Games} />
                <Route exact path="/account" render={accountDetails}/>
                <Route path="/games/:id" render={getGame} />
                <Route exact path="/login" component={LoginSignUp} />
                <Redirect to='404' />
            </Switch>
    );
};

И приложение теперь включает в себяниже.

import Routes from './routes/index.js';

class App extends React.Component {

    state = {
        loggedIn: true
    };

    render(){
        return (
            <div className="App">
                <Header/>
                <Routes/>
            </div>
        );
    }
}

Сначала я решил взять App из routes/index. Я основал мою исходную иерархию маршрутов, основанную на другом проекте, который не использовал react-router 4. Вот почему в другом проекте вложенные маршруты под маршрутом App достигли того, что я пытался. В react router 4 это было невозможно , следовательно, ошибка Cannot use Link outside of Router. Поэтому вместо этого я обернул App в Router в моем корневом индексном файле, затем обернул все другие маршруты в Switch в моем routes/index файле и импортировал их в App. App теперь может использовать Маршрутизатор для компонента Header, а также для других маршрутов, включенных в Switch.

Это также решило мою проблему за то, что пришлось пожертвовать exact path ради App. Поскольку я хотел использовать Header на каждой странице, я хотел, чтобы App был на каждой странице. Использование exact path помешало мне сделать это. Это также помешало мне использовать '/' для рендеринга Home. Когда я сделал App exact path равным path, я смог сделать это, но можно было ввести любой случайный необъявленный маршрут. Например, localhost:3000/poop не будет отображать NotFound, как я планировал,это просто ничего не сделает.

В итоге, переместив App из routes/index, он позволил мне обернуть его в каталог Router в корневом индексном файле. Затем, импортировав Routes в App, я смог позволить своему приложению ориентироваться на маршрут, сохраняя при этом Header на всех страницах. Кроме того, обернув все мои маршруты в Switch и имея корневой путь равный exact path, я мог правильно обрабатывать неизвестные пути и отображать компонент NotFound, используя <Redirect to='404' />.

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

Это не будет работать так, посмотрите, что у вас есть путь / для App, а затем / для Home, он не может соответствовать должным образом. Пожалуйста, просмотрите документы React Router. Вот ссылка на пример вложенных маршрутов * 1006. *

            <Route exact path="/" component={App} />
            <Route exact path="/home" component={Home}/>
            <Route exact path="/account" component={Account}/>
            <Route exact path="/games" component={Games}/>
            <Route exact path="/games/:id" render={getGame}/>
            <Route exact path='/login' component={LoginSignUp}/>
            <Route component={NotFound} />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...