Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router confusion

New to react & react-router.

I'm trying to understand this example:

https://github.com/ReactTraining/react-router/blob/1.0.x/docs/API.md#components-1

But this.props never contains main or sidebar. My code:

Main.js

ReactDOM.render(
    <Router>
      <Route path="/" component={App2}>
        <Route path="/" components={{main: Home, sidebar: HomeSidebar}}/>

      </Route>
    </Router>,
  document.getElementById('content')
);

App2.js

class App2 extends React.Component {
  render() {
    const {main, sidebar} = this.props;
    return (
        <div>
          <Menu inverted vertical fixed="left">
            {sidebar}
          </Menu>
          <Container className="main-container">
            {main}
          </Container>
        </div>
    );
  }
}

export default App2;

Home.js

import React from 'react';

class Home extends React.Component {

  render() {
    return (
      <div><h1>Home</h1></div>
    );
  }

}

export default Home;

HomeSidebar.js

class HomeSidebar extends React.Component {
  render() {
    return (
      <div>
        <p>I'm a sidebar</p>
      </div>

    );
  }
}

export default HomeSidebar;

I'm using electron with react dev tools. Whenever I debug, this.props contains neither main nor sidebar. Any idea why this is happening?

I've also tried using an IndexRoute, but it seems to not support a components prop.

Other things I've tried

ReactDOM.render(
    <Router>
      <Route component={App2}>
        <Route path="/" components={{main: Home, sidebar: HomeSidebar}}/>
      </Route>
    </Router>,
  document.getElementById('content')
);

ReactDOM.render(
    <Router>
      <Route path="/" component={App2} components={{main: Home, sidebar: HomeSidebar}}>
        <Route path="admin" components={{main: Admin, sidebar: AdminSidebar}}/>
      </Route>
    </Router>,
  document.getElementById('content')
);
like image 672
Jack Avatar asked Mar 05 '17 17:03

Jack


People also ask

What is the difference between react router Dom and react router?

react-router is the core package containing standard components and functionalities to implement routing in React applications. On the other hand, react-router-dom is a specialized package that you can use only in web-browser-based application development.

What problem does react router solve?

In React, routers help create and navigate between the different URLs that make up your web application. They allow your user to move between the components of your app while preserving user state, and can provide unique URLs for these components to make them more shareable.

What is not found in react router Dom?

To solve the error "Module not found: Error: Can't resolve 'react-router-dom'", make sure to install the react-router-dom package by opening your terminal in your project's root directory and running the command npm install react-router-dom and restart your development server.

Does react router work with react native?

React Router Native is published to npm. You can install it with either npm or yarn . Once you've initialized a new React Native project, you can copy/paste any of the examples into your index.


3 Answers

Looks like to have the components prop work you need use the <IndexRoute /> component instead of <Route />. In the react-router docs it mentions that IndexRoute has all of the same props as Route so doing

<IndexRoute components={{main: Main, side: Side}} />

works!

Full code:

React.render((
  <Router>
    <Route path="/" component={App} >
      <IndexRoute components={{main: Main, side: Side}}  />
    </Route>
  </Router>
), document.getElementById('app'))

Codepen: http://codepen.io/chmaltsp/pen/ZeLaPr?editors=001

Cheers!

like image 147
Philip Chmalts Avatar answered Nov 08 '22 02:11

Philip Chmalts


If you're using the current version of react-router (v4.0.0), it looks like they did away with the components prop on Routes: https://reacttraining.com/react-router/web/api/Route

You can render Routes anywhere, and they even have a sidebar example where they do just that. They have one set of Route components to render the main components and another set of Route components for sidebars, but both come from a single route config to keep it DRY.

To translate that to your code, you could create a route config:

const routes = [
  { path: '/',
    sidebar: Sidebar
    main: Main
  }
];

Then in Main.js

ReactDOM.render(
    <Router>
      <Route component={App2}>
        {routes.map((route, index) => (
          <Route
            key={index}
            path={route.path}
            component={route.main}
          />
        ))}
      </Route>
    </Router>,
  document.getElementById('content')
);

Then in App2.js

class App2 extends React.Component {
  render() {
    return (
        <div>
          <Menu inverted vertical fixed="left">
            {routes.map((route, index) => (
              <Route
                key={index}
                path={route.path}
                component={route.sidebar}
              />
            ))}
          </Menu>
          <Container className="main-container">
            {this.props.children}
          </Container>
        </div>
    );
  }
}

export default App2;
like image 23
James Ganong Avatar answered Nov 08 '22 02:11

James Ganong


The example from github was written 2 years ago (look here) and I'am not sure for which particular version it is related. And I'am not sure does it works now (because I am also new with react), but I know that you don't have use this approach to reach this aim, you can use separated component which will contains mainz and sidebar, here my example:

class App2 extends React.Component {
  render() {
    return (
        // Your Menu.
        // Your Container.
        <div>
          {this.props.children}
        </div>
    );
  }
}
class Home extends React.Component {
  render() {
    return (<div><h1>Home</h1></div>);
  }

}
class HomeSidebar extends React.Component {
  render() {
    return (<div><p>I am a sidebar</p></div>);
  }
}
class HomeWithSidebar extends React.Component {
  render() {
    return (
      <div>
          <Home />
          <HomeSidebar />
      </div>
    );
  }
}   
ReactDOM.render(
    <Router history={browserHistory}>
      <Route path="/" component={App2}>
        <Route path="/a2" components={HomeWithSidebar} />
      </Route>
    </Router>,
  document.getElementById('content')
);

PS: Don't forget use <Router history={browserHistory}> in your example.
And use IndexRoute in your example or specify another, like /a2 in my example.

like image 1
cn007b Avatar answered Nov 08 '22 03:11

cn007b