【问题标题】:Unable to access App component when using React Router使用 React Router 时无法访问 App 组件
【发布时间】:2020-02-05 06:57:50
【问题描述】:

我正在尝试使我的应用程序更受路线驱动/控制。我正在使用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;

我也试过这个没有&lt;Route exact path="/" component={Home}/&gt; 的路由设置,我试过使用&lt;Route exact path="/" component={App}&gt; 无济于事。

下面是我的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",

【问题讨论】:

    标签: reactjs react-redux react-router


    【解决方案1】:

    它不会那样工作,看看你有一个路径/ 对应App 然后/ 对应Home,它无法正确匹配。请查看 React Router 文档。这是nested routes 示例的链接。

    为了让你去某个地方看看这个对你的路由器的修改 你有:

                <Route path="/" component={App}>
                    <Route exact path="/404" component={NotFound} />
                    <Route exact 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>
    

    但效果会更好

                <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} />
    

    【讨论】:

    • 感谢您的回复。我可以点击 App 组件,但我收到一条错误消息 You should not use &lt;Link&gt; outside a &lt;Router&gt;,我假设它来自我的导航组件,它位于 App.js 中,但由于 App 本身被包裹在 &lt;Router&gt; 中,它不会感觉它的子组件(以及任何后续链接)也将被包裹在 &lt;Router&gt;?
    • 应该,如果您查看链接,您会发现确实如此。看起来它是在文档中完成的。
    • 我查看了链接,它很有帮助。从技术上讲,我的&lt;Link/&gt; 位于&lt;Header/&gt; 组件中,但仅在&lt;App/&gt; 中导入,其他任何地方都没有。就像&lt;App/&gt; 在&lt;Header/&gt; 之前被点击。除非&lt;Link/&gt; 必须在&lt;App/&gt; 中,而不是&lt;App/&gt; 的孩子。
    • 有什么方法可以使用路由将其他组件包装在&lt;App/&gt; 中?我希望&lt;App/&gt; 中的&lt;Header/&gt; 出现在所有页面上,我可以通过使App 的路径包含(不是确切路径)来做到这一点,但这会产生一个问题,即URL 可以是/not-valid-url然后它将呈现&lt;Header/&gt; 和一个空白页。
    【解决方案2】:

    我认为您应该以这种方式更改您的代码。 并在导入时检查应用组件的路径

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

    【讨论】:

    • 感谢您的回复。我尝试过这种方式,但我得到一个错误,说 You should not use &lt;Link&gt; outside a &lt;Router&gt; 我假设它来自我的导航组件,它位于 App.js 但由于 App 本身被包裹在 &lt;Router&gt;组件(以及任何后续链接)也将包含在 &lt;Router&gt;?另外,将exact path 用于Home 和path 用于App 有什么意义?
    • 是的,如果您的 &lt;Link/&gt; 在应用程序组件中,那么它应该可以工作
    • 从技术上讲,它在 &lt;Header/&gt; 组件中,但仅在 &lt;App/&gt; 中导入,其他任何地方都没有。就像&lt;App/&gt; 在&lt;Header/&gt; 之前被点击。除非 &lt;Link/&gt; 必须在 &lt;App/&gt; 中,而不是 &lt;App/&gt; 的子级。
    • 开关不维护App 与子组件,它似乎只显示App。当我取下开关时,效果更好。
    【解决方案3】:

    借助其他答案提供的见解,我能够想出一个解决方案来满足我的所有需求。

    这是我更新的文件。第一个是我的根index 文件。作为预防措施,我用this issue's answer 建议的import {BrowserRouter as Router} from 'react-router-dom' 替换了所有import {Router} from 'react-router' 实例。将所有react-router 实例替换为react-router-dom 有助于阻止You should not use &lt;Switch&gt; outside a &lt;Router&gt; 或You should not use &lt;Route&gt; outside a &lt;Router&gt; 错误。

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

    App 现在包括以下内容。

    import Routes from './routes/index.js';
    
    class App extends React.Component {
    
        state = {
            loggedIn: true
        };
    
        render(){
            return (
                <div className="App">
                    <Header/>
                    <Routes/>
                </div>
            );
        }
    }
    

    首先,我决定从routes/index 中删除App。我的原始路由层次结构基于另一个未使用react-router 4 的项目。这就是为什么在另一个项目中,App 路由下的嵌套路由实现了我想要的。在react router 4this was not possible 中,因此出现Cannot use Link outside of Router 错误。因此,我将App 包装在我的根索引文件中的Router 中,然后将所有其他路由包装在我的routes/index 文件中的Switch 中,并将它们导入App。 App 现在可以将路由器用于Header 组件以及包裹在Switch 中的其他路由。

    这也解决了我不得不为App 牺牲exact path 的问题。因为我想在每一页上使用Header,所以我希望App 出现在每一页上。使用exact path 阻止了我这样做。它还阻止我使用“/”来渲染Home。当我将App 的exact path 设置为path 时,我能够做到这一点,但是可以放入任何随机未声明的路线。例如,localhost:3000/poop 不会像我预期的那样呈现NotFound,它只会渲染什么。

    总之,通过将App 移出routes/index,我可以将其目录包装在根索引文件中的Router 中。然后通过将Routes 导入App,我可以让我的应用程序更受路由驱动,同时在所有页面上保持Header。此外,通过将我的所有路由包装在Switch 中并将根路径设为exact path,我可以正确处理未知路径并使用&lt;Redirect to='404' /&gt; 渲染NotFound 组件。

    【讨论】:

      猜你喜欢
      • 2016-08-18
      • 2016-07-20
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 2018-02-28
      • 1970-01-01
      • 2021-12-08
      相关资源
      最近更新 更多