Friday, July 27, 2018

Getting started with React Router

Leave a Comment

I am trying to setup my react app.

I am trying to understand how to integrate the routes with the app.

When I try to use AppRouter in my ReactDOM, I get an error message that says I shouldn't use Route outside the Router.

I don't understand what the error means. I can get rid of the error message when I remove the AppRouter line from my Provider, but that only creates a new error with the provider. I can't find an example of how to get started.

My app.js has:

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

My AppRouter has:

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

Can anyone see where I'm going wrong?

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

console errors after removing withRouter from the import statement:

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 

5 Answers

Answers 1

I think the problem is that your AppRouter is not returning anything. In the arrow function if you write () => {statement} it will execute the statement but if you write () => statement it will return it. So you should modify the AppRouter to:

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

More info about the arrow functions:

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

Hope it helps.

Answers 2

Hi @Mel I faced similar issue a few days back, and i resolved it as following:

  1. In your index.html, check that your id is app and not root.

  2. Modify your app.js to have:

    const jsx = (  <Provider store={store}>     <BrowserRouter>       <AppRouter />     </BrowserRouter>  </Provider> ); 
  3. Now, your AppRouter needs to be a class based component, so it would become as following after modifying:

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

If you still face issues, let me know, I can share more code.

Hope it helps! Happy Coding! ;)

Answers 3

index.js or appRouter.js should contain this type of routes written

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

while in your app.js you can write following and it should work fine

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

Answers 4

Just copy and paste the code. It will work. Message me if you have any issue

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

Answers 5

App.js

import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import AppRouter from './routers/AppRouter.js'; import configureStore from './store/configureStore.js'; import 'normalize.css/normalize.css'; import './styles/styles.scss'; import './firebase/firebase'; const store = configureStore();  const jsx = (     <Provider store={store}>         <AppRouter />     </Provider> );  ReactDOM.render(jsx, document.getElementById('app')); 

AppRouter.js

import React 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 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"; import withAuthentication from "../hoc/withAuthentication"; import AuthenticatedRoute from "../components/auth/AuthenticatedRoute";  const AppRouter = () => {   <BrowserRouter>     <div>       <Header />       <Switch>         <Route path="/" exact={true} component={Landing} />         <Route path="/Signin" component={SignIn} />         <Route path="/Pending" component={Pending} />         <Route path="/About" component={About} />         <Route path="/Users" component={Users} />         <Route path="/Menu" component={Menu} />         <Route component={ErrorNotice} />       </Switch>       <Footer />     </div>   </BrowserRouter>; };  export default AppRouter; 

First check if your AppRouter is rendering basically or not then we will go complicated.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment