If i want to upgrade from "react-router": "^2.0.0" to "react-router": "^4.0.0","react-router-dom": "^4.0.0".
My structure should be like this:
Main Component :is a container component for every thing (the
parent).
Nav Component :is used to navigate among my other child components and this component should appear always.
Child Components: Examples , About ,Test. where Test is the Default.
My old code which works as expected is like this :
-App.jsx
var {Route, Router, IndexRoute, hashHistory} = require('react-router');
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Main}>
<Route path="about" component={About}/>
<Route path="examples" component={Examples}/>
<IndexRoute component={Test}/>
</Route>
</Router>,
document.getElementById('app')
);
-Main Component is like this :
var React = require('react');
var Nav = require('Nav');
var Main = (props) => {
return (
<div>
<Nav/>
{props.children}
</div>
);
}
module.exports = Main;
-My Nav Component is like this :
var React = require('react');
var {Link, IndexLink} = require('react-router');
var Nav = () => {
return (
<div>
<IndexLink to="/" activeClassName="active" activeStyle={{fontWeight: 'bold'}}>Test</IndexLink>
<Link to="/about" activeClassName="active" activeStyle={{fontWeight: 'bold'}}>About</Link>
<Link to="/examples" activeClassName="active" activeStyle={{fontWeight: 'bold'}}>Examples</Link>
</div>
);
};
module.exports = Nav;
I try to upgrade like this:
-App.jsx
var { BrowserRouter, Route } =require('react-router-dom');
ReactDOM.render(
<BrowserRouter>
<div>
<Route path='/' component={Main} />
<Route path='/Test' component={Test}/>
<Route path='/about' component={About}/>
<Route path='/examples' component={Examples}/>
</div>
</BrowserRouter>,
document.getElementById('app')
);
-My Main Component has no changes
-My Nav Component is like this :
var React = require('react');
var {Link, NavLink} =require('react-router-dom');
var Nav = ()=>{
return(
<div>
<NavLink activeClassName="active" activeStyle={{fontWeight: 'Bold'}} to="/Test">Test</NavLink>
<NavLink activeClassName="active" activeStyle={{fontWeight: 'Bold'}} to="/about">About</NavLink>
<NavLink activeClassName="active" activeStyle={{fontWeight: 'Bold'}} to="/examples">Examples</NavLink>
</div>
);
}
module.exports = Nav;
I face the following problems :
The Test Component isn't the default like before.
The Main Component doesn't behave like a parent.
When i refresh the browser on Examples, i get the following error :
http://localhost:5000/examples net::ERR_CONNECTION_REFUSED
So you need to change your App.jsx module, so it's rendering only Main component, because now you can move your router in there. React Router v4 is no more rendering it's routes to props children. Now you need to declare it at specific place you want it to be rendered.
App.jsx
ReactDOM.render(
<Main/>,
document.getElementById('app')
);
Main component
var React = require('react');
var Nav = require('Nav');
var { HashRouter, Route, Switch } = require('react-router-dom');
var Main = (props) => {
return (
<HashRouter>
<Nav/>
<Switch>
<Route path='/about' component={About}/>
<Route path='/examples' component={Examples}/>
<Route component={Test}/>
</Switch>
</HashRouter>
);
}
module.exports = Main;
So now your Main component can behave like parent.
If you remove path attribute for Route component, it will behave like default. Also you might noticed I've added Switch component. It should assure one route is rendered exclusively. You can check detailed info in manual.
Before, you had used hashHistory for your Router, now you can do the same using HashRouter. This should resolve error you get.
Related
I was applying authenication in my project in React.js by using protectes routes. First i was using Redirect component from react-router-dom but then i have found out the changes they made in react-router-dom than i applied the navigate component.
import {BrowserRouter,Routes,Route,Navigate} from 'react-router-dom';
import './App.css';
import Navigation from './components/shared/Navigation/Navigation';
import Authenticate from './pages/Authenticate/Authenticate';
import Home from './pages/Home/Home';
import Login from './pages/Login/Login';
import Register from './pages/Register/Register';
const isAuth = true;
function App() {
return (
<div className="App">
<BrowserRouter>
<Navigation/>
<Routes>
<Route exact path='/' element={<Home/>}></Route>
{/* <Route exact path='/register' element={<Register/>}></Route>
<Route exact path='/login' element={<Login/>}></Route> */}
{/* <Route exact path='/authenticate' element={<Authenticate/>}></Route> */}
<GuestRoute exact path='/authenticate' element={<Authenticate/>}></GuestRoute>
</Routes>
</BrowserRouter>
</div>
);
}
const GuestRoute = ({children,...rest}) =>{
return(
<Route {...rest} render = {({location})=>{
return isAuth ?(
<Navigate to = '/rooms'state = {{from : location}} replace />
)
:(
children
)
}}></Route>
)
}
export default App;
This is my code after using the navigate component my screen not showing any thing there must be some kind of logical error in it. Kindly help me to resolve this error.
your app is showing nothing because the route /rooms does not match any routes in the <Routes /> component
Hello guys so I'm trying to create a web app using react-bootstrap and use BrowserRouter to link each of the component I have. I already wrap the index JS with BrowserRouter and I already add the Switch and Route tag to the navigation component, but when I tried to implement the navigation into app.js the web start to load endlessly without showing anything. Can anyone please help me with it ?
here is my navigation code:
import React from 'react'
import Facilities from './Facilities'
import Room from './Room'
import Booking from './Booking'
import Contact from './Contact'
import App from '../App'
import { Route, Switch } from 'react-router-dom'
const Navigation = () => {
return (
<>
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
</>
)
}
export default Navigation
If the App component is the default App component after creating a React app using npx create-react-app ... command, I suggest you not use another App name for other files in your project.
But if you want to use your Navigation component as the root component, you could try this:
Option 1:
index.js
import ReactDOM from "react-dom";
import Navigation from "./Navigation ";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Navigation />,
rootElement
);
Navigation.js
import React from 'react'
import Facilities from './Facilities'
import Room from './Room'
import Booking from './Booking'
import Contact from './Contact'
import App from '../App'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
const Navigation = () => {
return (
<Router>
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
</Router>
)
}
export default Navigation
Option 2:
index.js: add BrowserRouter as Router from react-router-dom here
ReactDOM.render(
<Router>
<Navigation /> {/* put the Navigation component here */}
</Router>,
rootElement
);
Navigation.js: delete BrowserRouter as Router from react-router-dom here
return (
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
)
Switch is not a link to a component, but a decision about what is to be rendered in this space.
Imagine it to be a (pseudo-code)
switch(path){
case "path1": route(Component1); break;
case "path2": route(Component2); break;
default: route("*"); break;
Therefore, put in the component (or at the highest level where you are branching based on path), and not navigation.
The way we have done (with react-bootstrap) in our apps is this way:
// App.js
import Navigation from "./Navigation";
import Facilities from "./Facilities" .. and so on
const App = ({}) => {
return
<Navigation />
<Switch>
<Route path="/facilities" component={Facilities}/>
<Route path="/rooms" component={Rooms}/>
</Switch>
}
// Navigation.js
import Link from "react-bootstrap/Link";
const Navigation = () => {
<div>
<Link to="/facilities"/>
<Link to="/rooms"/>
</div>
}
Could anyone help me with this question?
I'm a bit lost when using different routes containing subroutes.
I am trying to add routes with different paths.
I would like to have a default route with all the features and an alternate Event route separately.
From now on I am grateful for the attention and thank you very much.
index.js
Contains the two different routes. Layout and Event.
The Route Layout contains another Routes component inside.
const Root = (
<BrowserRouter>
<Route component={App}>
<Route component={Layout}/>
</Route>
<Route path="/event/:id" component={Event}/>
</BrowserRouter>
)
ReactDOM.render(Root , document.getElementById('root'));
App.js
Component to be loaded. Layout or Event
class App extends Component {
render() {
const { children } = this.props;
return (
<div>{children}</div>
);
}
}
export default App;
RouterLayout.js --> This route is a subroute that is inside the Layout
const Router = () => (
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/about' component={About}/>
</Switch>
)
export default Router
Layout.js
class Layout extends Component {
render() {
const { children } = this.props;
return (
<Content className="column is-8 content-page">
<RouterLayout/>
<div>{children}</div>
</Content>
);
}
}
export default Layout;
I was able to solve this way
<BrowserRouter>
<div>
<Route exact path="/page/*" component={Layout}/>
<Route exact path="/event/:id" component={EmptyLayout}/>
</div>
</BrowserRouter>
Goal
I'm trying to extract the <Switch> with its <Route>'s out to a different module.
Problem
The url is being changed to the new path, but the content doesn't (only when I refresh it changes).
I'm trying to understand what am I missing.
EDITED:
live example: https://stackblitz.com/edit/separated-switch-module
working example:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/contacts" component={Contacts} />
</Switch>
</div>
</BrowserRouter>
failing exmaple:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<SwitchedRoutes/>
</div>
</BrowserRouter>
EDITED:
SwitchedRoutes:
import React from "react";
import { observer, inject } from "mobx-react";
import { Switch, Route } from "react-router-dom";
#inject('pageStore')
#observer
export default class extends React.Component {
render(){
const {
home,
contacts
} = this.props.pageStore.pages;
return (
<Switch>
<Route exact path={home.path} render={()=> <Home />} />
<Route path={contacts.path} render={()=> <Contacts/>} />
</Switch>
)
}
}
Since react-router v4 changed an API a bit you need to give to the all underlying components such as Switch, Link and etc a router context. (Something like subscriber to the routing stuff), as soon as you disconnects the module to the separate file it loses the context.
just add this to the SwitchedRoutes.js
import React from 'react';
import { withRouter } from 'react-router'
import {Switch, Route} from 'react-router-dom';
import {inject, observer} from 'mobx-react';
const Home = () => <h1>Home</h1>;
const Contacts = () => <h1>Contents</h1>;
const switchedRouter = inject('store')(observer(props => {
const {home, contacts} = props.store.routes;
return(
<Switch>
<Route exact path={home.path} component={Home}/>
<Route path={contacts.path} component={Contacts}/>
</Switch>
);
}));
export default withRouter(switchedRouter)
we simply wrapped the component with withRouter HoC which provides us a correct react-router context.
https://separated-switch-module-j92psu.stackblitz.io
I'm trying to get a react router to work. This is my code:
var hashHistory = require('react-router-dom').hashHistory;
var BrowserRouter = require('react-router-dom').BrowserRouter;
var Route = require('react-router-dom').Route;
var ReactDOM = require('react-dom');
var React = require('react');
var Index = require('./index');
var Login = require('./login');
ReactDOM.render(
<BrowserRouter history={hashHistory}>
<div>
<Route path="/" component={Index} />
<Route path="/login" component={Login} />
</div>
</BrowserRouter>,
document.getElementById('main-content')
);
and then later in my index.js i do this:
<div className="navbar-nav" onClick={() => this.props.history.push('/login')}>
Log in
</div>
This makes the url change to /login but it doesn't render the login file. What is wrong?
It seems like when you switch to /login it matches to /:
<Route path="/" component={Index} />
Try to add exact prop to the route, like this:
<Route exact path="/" component={Index} />
What you can also try to do is to change the matching order:
<Route path="/login" component={Login} />
<Route path="/" component={Index} />
Is your index.js a separate file or component? If so you need to use the router middleware to connect it to react-router.
Either import the Link component and use it directly,
or bind a click handler and wrap withRouter to mount the router calls to the props.
import React from 'react';
import {Link, withRouter} from 'react-router';
class Test extends React.Component {
constructor(props) {
super(props);
this.handleLink = this.handleLink.bind(this);
}
handleLink() {
this.props.history.push('/login')
}
render() {
return (
<div>
<Link to={{pathname: '/login'}}>Link</Link>
<button onClick={this.handleLink}>Click</button>
</div>
);
}
}
export default withRouter(Test);