How do I handle Multiple Routes In App.js? - javascript

I'm new to react and now learning react-router.
I am trying to have multiple routes within the BrowserRouter and I am not sure why it isn't working.
My code is this
import React, { Component } from 'react';
import {database} from '../firebase';
import _ from 'lodash';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Link} from 'react-router-dom';
import List from './List';
import NewPost from './NewPost';
class App extends Component {
render() {
return (
<div className="App container">
<header className="App-header">
<h1 className="App-title">Here We Go Again</h1>
</header>
<hr/>
<BrowserRouter>
<Switch>
<Route path='/' component={List}/>
<Route path='/new' component={NewPost}/>
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
Regardless of the path I go to, it only shows the first one in the list. I have tried moving them around so I know that for sure. And the functionality of them all still work. It's just a matter of rendering them one at a time.
<BrowserRouter>
<Switch>
<Route path='/' component={List}/>
<Route path='/new' component={NewPost}/>
</Switch>
</BrowserRouter>
As you can see I tried some other possible solutions on stack overflow liek adding Switch but it still didn't work.
Any idea how to fix it or what I'm doing wrong?

You need to add the word exact to the first route. It is currently matching anything with a /.
<BrowserRouter>
<Switch>
<Route path='/' exact component={List}/>
<Route path='/new' component={NewPost}/>
</Switch>
</BrowserRouter>

Related

Can't get react-router-dom to work (seeing blank page)

This is my App component that has 3 child components: Home, Contact and Procedures. I'm trying to make each child component into its own url route.
However right now I'm just seeing a blank page
FYI- I'm using react-router-dom#6.0.2
import {BrowserRouter, Routes, Route} from 'react-router-dom';
import Home from './Home.js'
import Contact from './Contact.js'
import Procedures from './Procedures.js'
import './App.css';
function App() {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" component={Home} />
<Route path="/procedures" component={Procedures} />
<Route path="/contact" component={Contact} />
</Routes>
</BrowserRouter>
);
}
export default App;
In react-router-dom version 6 you should use element instead of component, also be sure to reference the element you want to render as JSX. By the way, there is no longer any "exact" attribute.
Should look like this on your code:
<Route path="/" element={<Home />} />

Migrate 'react-router' into 'react-router-dom' (v4)

I am learning React Routing and I am watching this tutorial:
https://www.youtube.com/watch?v=1iAG6h9ff5s
Its 2016 tutorial so I suppose something changed because 'react-router' not working anymore and I am supposed to use 'react-router-dom'.
I found that I must uninstall 'history' and 'react-router' and use 'react-router-dom' instead, but It not working as expected when I change it.
How to edit this to make it working with 'react-router-dom'?
import React from "react";
import ReactDOM from "react-dom";
import {Router, Route, IndexRoute, hashHistory} from "react-router";
import Layout from "./pages/Layout";
import Archives from "./pages/Archives";
import Featured from "./pages/Featured";
import Settings from "./pages/Settings";
const app = document.getElementById('app');
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Layout}>
<IndexRoute component={Featured}></IndexRoute>
<Route path="archives" component={Archives}></Route>
<Route path="settings" component={Settings}></Route>
</Route>
</Router>,
app);
My edit:
import React from "react";
import ReactDOM from "react-dom";
import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
import Layout from "./pages/Layout";
import Archives from "./pages/Archives";
import Featured from "./pages/Featured";
import Settings from "./pages/Settings";
const app = document.getElementById('app');
ReactDOM.render(
<Router>
<Route path="/" component={Layout}>
<Route path="/featured" component={Featured}/>
<Route path="/archives" component={Archives}/>
<Route path="/settings" component={Settings}/>
</Route>
</Router>,
app);
Also pushState not working...
Layout.js
import React from "react";
import {Link} from "react-router-dom";
export default class Layout extends React.Component {
navigate() {
this.props.history.pushState(null, "/");
}
render() {
return (
<div>
{this.props.children}
<h1>Welcome</h1>
<button onClick={this.navigate.bind(this)}>Featured</button>
</div>
);
}
}
When I click to Link url change, but content is not loaded... Also when I access url I get "Cannot GET" error
After watching the video, you probably want something like this. At first this would not be so easy to understand but after seeing a few of them you digest it. First you render your Layout with one Route. Then in this top route, you use other Routes to setup your components.
We usually use exact props for a top root like /. If you don't setup your app like that, for example all your routes is in your top Router config, then to use a route something like /featured we must have exact prop. If we don't use it Router always hit / path and we always see the top level component.
But, in your situation, you want other components to be routed in your top level component. So, we drop exact prop here.
Also you can use push to change history.
Update
After think about the navigation button named "Featured", I think you want the Featured component rendered as default one here. When hit the button again you will come back to Featured one. I've changed the code according to that. In this version, we add a / route in the Layout and point it to Featured. So, when we come here it is rendered. But, we use exact prop here since we also want routes like "/featured", "/archives" and "/settings".
export default class Layout extends React.Component {
navigate = () => this.props.history.push("/");
render() {
return (
<div>
<h1>Welcome</h1>
<Link to="/featured">Featured</Link>
<Link to="/archives">Archives</Link>
<Link to="/settings">Settings</Link>
<br />
<button onClick={this.navigate}>Featured</button>
<Route exact path="/" component={Featured} />
<Route path="/featured" component={Featured} />
<Route path="/archives" component={Archives} />
<Route path="/settings" component={Settings} />
<div>
Some other info.
</div>
</div>
);
}
}
const app = document.getElementById('root');
ReactDOM.render(
<Router>
<Switch>
<Route path="/" component={Layout} />
</Switch>
</Router>,
app);

How to redirect using react-router-dom

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import Reducer from './Reducer/';
import {HashRouter as Router, Route, Redirect} from 'react-router-dom';
import Login from './Components/login.jsx';
import User from './Components/User.jsx';
const store = createStore(Reducer, applyMiddleware(thunk));
ReactDOM.render(
<Provider store={store}>
<Router>
<div>
<Route path='/login' component={Login}/>
<Route path='/user' component={User}/>
</div>
</Router>
</Provider>
,document.getElementById('root'));
When the user hits the '/' url i want them to be in the login component, but if i do:
<Route path='/' component={Login}/>
The login component always shows up on every different route.
My question is. On the landing page "/" how can i make it so it is the login component, but i dont want it to be there if i go to the user component
You could do <Route path='/' component={Login} exact /> to specify only rendering that component when its exactly / and nothing more.
You should use exact in your route:
<Route path="/" component={Login} exact />
In addition, you should consider using Switch component to wrap your routes. This will render exactly one route. By design, React Router renders all routes that match. Read about Switch here: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md

electron + react router: initial app is not at root route

I have a setup in electron with react router. When I load the app into my browser, and don't go via electron, everything works fine, and the router is good.
When I use it in electron however, my software is not at the root route initially. I can navigate to the root route with the links I created, and that works fine. But it's not there initially, I get a 404. But I don't get any errors as such.
So when i start it, it looks like this:
But the Links all work, so I can click for example on Home at am redirected to the Home route:
My switch looks like this:
<Switch>
<Route exact path='/' component={Home}/>
<Route component={NotFound}/>
</Switch>
And that component sits in another component:
import React from 'react';
import Header from './Header.jsx'
import Main from './Main.jsx'
export default class App extends React.Component {
render() {
return (
<div style={{textAlign: 'center'}}>
<Header />
<Main />
</div>);
}
}
which sits in this component:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';
import {BrowserRouter} from 'react-router-dom'
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'));
and here is also the Main.js which holds the Routes:
const Main = () => (
<main>
<Switch>
<Route exact path='/' component={Home}/>
<Route component={NotFound}/>
</Switch>
</main>
)
So as far as I am concerned, everything should be working fine, and, as I said, it does in the browser. But electron does not seem to start my react router at /. Why could this be?

How to define child routes as react components in react-router?

I have main.js:
import { render } from 'react-dom';
import { browserHistory, Router, Route, IndexRoute } from 'react-router';
import Home from './containers/Home';
import ApplicationsRoutes from './applications/routes';
render((
<Router history={browserHistory}>
<Route path="/" component="div">
<IndexRoute component={Home} />
<ApplicationsRoutes />
</Route>
</Router>
), document.getElementById('app'));
And /application/routes.js :
import { browserHistory, Router, Route, IndexRoute } from 'react-router'
import ApplicationsHome from './containers/ApplicationsHome';
export default () => (
<Route path="applications" component={ApplicationsHome} />
);
I was expecting that route from /application/routes.js will be added to the main router and so ApplicationsHome will be rendered for path /applications
Unfortunately, this is not a case. I am getting error:
Location "/applications" did not match any routes
For me it looks like such a way to compose Router does not work, but I cannot understand what is right way to do this.
In general, when you do this, you should consider using the PlainRoute syntax instead of the JSX syntax, then use getChildRoutes on the parent routes to resolve the child routes, per the huge-apps example: https://github.com/rackt/react-router/tree/master/examples/huge-apps
This will then let you easily configure code-splitting and dynamic routes down the road.
For singular routes you can export your route as a JSX element:
export default <Route path="applications" component={ApplicationsHome} />;
And include it like this:
{SomeRoute}
For multiple routes you can't export them as you have in a function, you'll get a JSX error saying you can't have adjacent components without a wrapping element. In that case you would have to do:
export default (
<Route>
<Route path="/about" component={About} />
<Route path="/services" component={Services} />
</Route>
);
And use it:
{ApplicationsRoutes}

Categories

Resources