【问题标题】:Getting started with React RouterReact 路由器入门
【发布时间】:2018-07-16 00:43:53
【问题描述】:

我正在尝试设置我的 react 应用程序。

我正在尝试了解如何将路线与应用程序集成。

当我尝试在我的 ReactDOM 中使用 AppRouter 时,我收到一条错误消息,指出我不应该在路由器之外使用 Route。

我不明白错误的含义。当我从提供程序中删除 AppRouter 行时,我可以摆脱错误消息,但这只会在提供程序中创建一个新错误。我找不到如何开始的示例。

我的 app.js 有:

import React from 'react';
import ReactDOM from 'react-dom';

import { Provider } from 'react-redux';
import AppRouter from './routers/AppRouter.js';
import { BrowserRouter } from 'react-router-dom';
import configureStore from './store/configureStore.js';
// import { startSetUsers } from './actions/users';


import 'normalize.css/normalize.css';
import './styles/styles.scss';
import './firebase/firebase';
// import * as firebaseui from 'firebaseui'

//import './playground/promises';


const store = configureStore();

const jsx = (
    <Provider store={store}>
        <AppRouter />
    </Provider>
);

ReactDOM.render(jsx, document.getElementById('app'));

我的 AppRouter 有:

import React from 'react';
import { connect } from 'react-redux';
import { BrowserRouter, Route, Switch, Link, NavLink, withRouter } from 'react-router-dom';
import Header from '../components/Header.js';
import Footer from '../components/Footer.js';

import Dashboard from '../components/home/Dashboard.js';
import Landing from '../components/home/Landing.js';
import ErrorNotice from '../components/ErrorNotice.js';
import SignIn from '../components/auth/RegisterPage.js';
import Pending from '../components/auth/PendingPage.js';
import SignInSuccess from '../components/auth/SignInSuccess.js';


import Users from '../components/users/UserDashboard.js';

// this Higher Order Component wraps the app and listens for Firebase auth change state event
// when this state changes, it updates the store
import withAuthentication from '../hoc/withAuthentication';
import AuthenticatedRoute from  '../components/auth/AuthenticatedRoute';

const AppRouter = () => {
    return (
            <div>
                <Header />
                <Switch>
                    <Route path="/" exact={true} component={Landing} />
                    {/* Authentication Related routes */}
                    <Route path="/Signin" component={SignIn} />
                    {/* This route no longer required. Was used when uiConfig has a redirect URL */}
                    {/* <Route path="/Loading" component={SignInSuccess} /> */}
                    <Route path="/Pending" component={Pending} />
                    {/* PUBLIC ROUTES */}
                    <Route path="/Users" component={Users} />
                    <Route path="/Menu" component={Menu} />
                    {/* AUTHENTICATED ROUTES */}
                    {/* Places routes that require authenitcation here and use the AuthenticatedRoute */}
                    <AuthenticatedRoute path="/Dashboard" component={Dashboard} />
                    <Route component={ErrorNotice} />
                </Switch>
                <Footer />
            </div>
    )
}



// set up passing of store state as component props
const mapStateToProps = state => ({
    authUser: state.sessionState.authUser,
});

// connect this component to the store
// wrap withRouter to ensure that Links work: => https://reacttraining.com/react-router/core/guides/redux-integration/blocked-updates
export default withRouter(connect(mapStateToProps)(AppRouter));

谁能看出我哪里出错了?

修改了 AppRouter.js

import React from "react";
import { connect } from "react-redux";
import {
  BrowserRouter,
  Route,
  Switch,
  Link,
  NavLink,
  withRouter
} from "react-router-dom";
import Header from "../components/Header.js";
import Footer from "../components/Footer.js";

import Dashboard from "../components/home/Dashboard.js";
import Landing from "../components/home/Landing.js";
import ErrorNotice from "../components/ErrorNotice.js";
import SignIn from "../components/auth/RegisterPage.js";
import Pending from "../components/auth/PendingPage.js";
import SignInSuccess from "../components/auth/SignInSuccess.js";

import About from "../components/footerlinks/company/About.js";
import Users from "../components/users/UserDashboard.js";

// this Higher Order Component wraps the app and listens for Firebase auth change state event
// when this state changes, it updates the store
import withAuthentication from "../hoc/withAuthentication";
import AuthenticatedRoute from "../components/auth/AuthenticatedRoute";

const AppRouter = () => {
  <BrowserRouter>
    <div>
      <Header />
      <Switch>
        <Route path="/" exact={true} component={Landing} />
        {/* Authentication Related routes */}
        <Route path="/Signin" component={SignIn} />
        {/* This route no longer required. Was used when uiConfig has a redirect URL */}
        {/* <Route path="/Loading" component={SignInSuccess} /> */}
        <Route path="/Pending" component={Pending} />
        {/* PUBLIC ROUTES */}
        <Route path="/About" component={About} />
        <Route path="/Users" component={Users} />
        <Route path="/Menu" component={Menu} />
        {/* AUTHENTICATED ROUTES */}
        {/* Places routes that require authenitcation here and use the AuthenticatedRoute */}
        <AuthenticatedRoute path="/Dashboard" component={Dashboard} />
        <Route component={ErrorNotice} />
      </Switch>
      <Footer />
    </div>
  </BrowserRouter>;
};

// set up passing of store state as component props
const mapStateToProps = state => ({
  authUser: state.sessionState.authUser
});

// connect this component to the store
// wrap withRouter to ensure that Links work: => https://reacttraining.com/react-router/core/guides/redux-integration/blocked-updates
export default connect(mapStateToProps)(AppRouter);

从 import 语句中删除 withRouter 后出现控制台错误:

Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.
    in Route (created by AppRouter)
    in AppRouter (created by Connect(AppRouter))
    in Connect(AppRouter)
    in Provider

Warning: AppRouter(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
printWarning @ warning.js:33
warning @ warning.js:57
warnIfInvalidElement @ ReactCompositeComponent.js:51
mountComponent @ ReactCompositeComponent.js:193
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
performInitialMount @ ReactCompositeComponent.js:370
mountComponent @ ReactCompositeComponent.js:257
mountComponent @ ReactReconciler.js:45
mountComponentIntoNode @ ReactMount.js:104
perform @ Transaction.js:143
batchedMountComponentIntoNode @ ReactMount.js:126
perform @ Transaction.js:143
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:97
_renderNewRootComponent @ ReactMount.js:319
_renderSubtreeIntoContainer @ ReactMount.js:401
render @ ReactMount.js:422
(anonymous) @ app.js:29
__webpack_require__ @ bootstrap 8dde10c53183363cc06e:19
(anonymous) @ bundle.js:50261
__webpack_require__ @ bootstrap 8dde10c53183363cc06e:19
module.exports @ bootstrap 8dde10c53183363cc06e:62
(anonymous) @ bootstrap 8dde10c53183363cc06e:62
invariant.js:42 Uncaught Error: AppRouter(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object

【问题讨论】:

  • 使用您从react-router-dom 导入的BrowserRouter 作为AppRouter 中的最顶层组件,将所有内容包装在其中,它应该可以工作。 const AppRouter = () =&gt; &lt;BrowserRouter&gt;{/* ... */}&lt;/BrowserRouter&gt;
  • 嗨@Tholle - 我试过了,但我得到了同样的错误。
  • 这样做并删除您在导出时使用的withRouter HOC,然后重试。
  • 你的意思是这样的:export default(connect(mapStateToProps)(AppRouter)); ?我知道这是错误的 - 尝试这样做会产生一长串错误,但我不知道从哪里开始弄清楚需要什么。
  • 您能在codesandbox.io/s/new 上创建一个添加了BrowserRouter 的示例吗?

标签: reactjs react-router


【解决方案1】:

我认为问题在于您的AppRouter 没有返回任何内容。在箭头函数中,如果你写() =&gt; {statement},它将执行语句,但如果你写() =&gt; statement,它将返回它。所以你应该将AppRouter修改为:

const AppRouter = () => (
  <BrowserRouter>
    ...
  </BrowserRouter>
);

更多关于箭头函数的信息:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

希望对你有帮助。

【讨论】:

  • 嗨@peetya,非常感谢。我尝试了您的建议,但我收到一条错误消息:失败的道具类型:无效的道具component 类型为object 提供给Route,预期为function。虽然登陆页面确实加载。这可能是迈向解决方案的一步。我会阅读更多内容。
  • 不客气,如果您需要进一步的帮助,请告诉我,我会尽我所能:)
【解决方案2】:

嗨@Mel,几天前我遇到了类似的问题,我解决了如下:

  1. 在您的 index.html 中,检查您的 id 是 app 而不是 root

  2. 修改您的 app.js 以具有:

    const jsx = (
     <Provider store={store}>
        <BrowserRouter>
          <AppRouter />
        </BrowserRouter>
     </Provider>
    );
    
  3. 现在,你的AppRouter需要是一个基于类的组件,所以修改后变成如下:

// All your imports come here

  class AppRouter extends Component {
     render() {
       let routes = (
          <Switch>
            <Route path="/" exact={true} component={Landing} />
            <Route path="/Signin" component={SignIn} />
            <Route path="/Pending" component={Pending} />
            <Route path="/Users" component={Users} />
            <Route path="/Menu" component={Menu} />
            <AuthenticatedRoute path="/Dashboard" component={Dashboard} />
            <Route component={ErrorNotice} />
          </Switch>
       );
       return (
         <div>
            <Header />
            {routes}
            <Footer />
        </div>
       );
     }
   }
   const mapStateToProps = state => ({
      authUser: state.sessionState.authUser
   });
   export default withRouter(connect(mapStateToProps)(AppRouter));

如果您仍然遇到问题,请告诉我,我可以分享更多代码。

希望对您有所帮助!快乐编码! ;)

【讨论】:

  • 非常感谢。我试过了,但我仍然得到2个错误,如下:1。失败的道具类型:提供给Routeobject类型的无效道具component,预期function 2.必须返回有效的React元素(或null)。您可能返回了未定义、数组或其他一些无效对象。
  • 嗨@Mel,关于您当前的错误: 1. 此错误与您的某些组件中返回多个语句有关,请see this 供参考。 2. 第二个错误是你的 中传入的某个组件不正确。请检查this link,我已经为基于函数和类的组件的语法创建了一个 JSFiddle 示例。
  • 我更新了 Fiddle 示例以提供更多信息:这是更新后的链接:jsfiddle.net/kapil5harma/0e4zopf3/23
【解决方案3】:

index.jsappRouter.js 应包含此类编写的路由

import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import store from './redux-state.js';


ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter>
      <App>
        <Switch>
          <Route path="/" exact={true} component={Landing} />
          <Route exact path="/" component={Home}/>
          <Route component={Error404} />
        </Switch>
      </App>
    </BrowserRouter>
  </Provider>,
  document.getElementById('appRoot'),
  renderCommon
);

在您的 app.js 中,您可以编写以下内容,它应该可以正常工作

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

function mapStateToProps(state) {
  return {};
}

function mapDispatchToProps(dispatch) {
  return {};
}

class App extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      {this.props.children}
    )
  }
}

【讨论】:

    【解决方案4】:

    只需复制并粘贴代码。它会起作用的。有问题可以私信我

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import { BrowserRouter, Route, Switch } from 'react-router-dom';
    import Header from '../components/Header.js';
    import Footer from '../components/Footer.js';
    import NotFound from "../../ui/pages/notfound";
    
    import Dashboard from '../components/home/Dashboard.js';
    import Landing from '../components/home/Landing.js';
    import ErrorNotice from '../components/ErrorNotice.js';
    import SignIn from '../components/auth/RegisterPage.js';
    import Pending from '../components/auth/PendingPage.js';
    import SignInSuccess from '../components/auth/SignInSuccess.js';
    
    
    import Users from '../components/users/UserDashboard.js';
    
    // this represent ur actions
    import { togglemenu } from "../../../actions/index";
    import { bindActionCreators } from 'redux';
    
    
    class AppRouter extends Component {
      render() {
        return (
          <BrowserRouter>
            <Header />
              <div>
                <Switch>
                  <Route path="/" exact={true} component={Landing} />
                  <Route path="/Signin" exact={true} component={SignIn} />
                  <Route path="/Pending" exact={true} component={Pending} />
                  {/* PUBLIC ROUTES */}
                  <Route path="/Users" exact={true} component={Users} />
                  <Route path="/Menu" exact={true} component={Menu} />
                  <Route component={NotFound} />
                </Switch>
              </div>
            <Footer />
         </BrowserRouter>
       )
     }
    }
    
    
    function mapStateToProps(state) {
      return {
       // ur redux state
       home: state.home
      }
    }
    function mapDispatchToProps(dispatch) {
      return bindActionCreators({
      // ur redux action
      togglemenu: togglemenu
      }, dispatch)
    }
    
     export default connect(mapStateToProps, mapDispatchToProps)(AppRouter);
    

    【讨论】:

    • 感谢分享您的代码@Abundance - 我似乎没有采用与您在准备代码时使用的方法类似的方法 - 所以我不确定如何使用您的想法。
    • 向我解释你是如何设置你的项目的,以便我可以帮助你。
    • 只说复制和粘贴不是建设性的答案。
    • 如上所述。感谢您提供帮助。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    相关资源
    最近更新 更多