React Router入门

时间:2018-07-16 00:43:54

标签: reactjs react-router

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

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

当我尝试在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);
从导入语句中删除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

4 个答案:

答案 0 :(得分:2)

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

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

有关箭头功能的更多信息:

  

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

希望有帮助。

答案 1 :(得分:1)

@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 :(得分:0)

index.js appRouter.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}
    )
  }
}

答案 3 :(得分:-1)

只需复制并粘贴代码。它会工作。如果您有任何问题,请告诉我

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