react-router-dom : updates url but does not render the new component - reactjs

I am a bit lost with this issue for a whole day.
On button click the url changes but does not render the new page and I don't understand why.
I am using react-dom-router 5.2.0
INDEX JS
import {Router} from 'react-router-dom';
import history from './history';
ReactDOM.render(
<React.StrictMode>
<Router history={history}>
<App />
</Router>
</React.StrictMode>,
document.getElementById('root')
);
APP JS
import Server from './Server';
import React from 'react';
function App() {
return (
<Server />
);
}
export default App;
SERVER JS
export default class Server extends Component
{
render()
{
return(
<div className="Homepage" >
<h1 className="header">Server</h1>
<button className="button"
onClick={() => history.push('/control')}>
Lets go
</button>
}
</div>
);
}
}
Please Note : I added <Control/> directly in the render method above and it renders the component all well .
CONTROL JS
import React, {Component} from 'react';
import Page2_View from './Page2_View';
export default class Control extends Component
{
constructor(props)
{
super(props);
}
render()
{
return(
<Page2_View/>
);
}
}
Page2_View
import React, {Component} from 'react';
const Page2_View = (props) =>
{
return(
<h1> PAGE 2 VIEW </h1>
);
}
export default Page2_View;
ROUTES JS
import {BrowserRouter as Router, Route, Redirect, Switch} from 'react-router-dom';
const Routes = () =>
{
return(
<Router>
<div>
<Switch>
<Route exact path="/test" component={Server}/>
<Redirect from = '/test' to = '/control'/>
<Route exact path="/control" component={Control}/>
</Switch>
</div>
</Router>
);
}
export default Routes;
HISTORY JS
import {createBrowserHistory as history} from 'history';
export default history();
I appreciate all the help. Thank you

I think the problem is that react-router-dom is not aware of this history.push('/control') you're doing; i.e. if you want to redirect to another route, it should be through react-router, not outside of it.
You have a few options:
Use the useHistory hook: https://reacttraining.com/react-router/web/api/Hooks/usehistory
Your button could be wrapped in a Link component: https://reacttraining.com/react-router/web/api/Link
Get the router through props with the withRouter component, as explained in: Programmatically navigate using react router V4.

I have realized what I was doing wrong and was able to solve my issue.
The key was to understand that the Router module from react-router-dom
comes with three props : path , history, and component.
So in order to redirect a page on button click all I had to do embed all my Routes between tag in the App.js
APP JS
function App() {
return (
<Router>
<Switch>
<Route exact path="/test" component={componentA}/>
<Route exact path="/test2" component={componentB}/>
</Switch>
</Router>
);
}
export default App;
And then you can use button onClick to redirect
COMPONENTA JS
<button variant="secondary"
className="button" size="lg"
onClick={() => this.props.history.push('/test2')}>
RedirectTo
</button>
Hope this will be helpful to others who come across this!

In server.js file instead of button use navlink or link from reactrouter below is a saple code
<NavLink to="/control">control</NavLink>
Import every component to routing component then use router switch and redirect statements like below
import Main from './component/Main'
import Welcome from "./component/welcome"
import { Route, BrowserRouter as Router, Switch,Redirect } from 'react-router-dom'
function App() {
return (
<Router>
<Switch>
<Redirect from="/" to="/home" exact />
<Route exact path="/home" component={Main} />
<Route path="/welcome" component={Welcome} />
</Switch>
</Router>
);}
export default App;
and in your component where you re clicking import link or nav link i prefer using navlink
and use it to redirect to page on click
import { NavLink } from 'react-router-dom'
<NavLink to="/home">home</NavLink>

Related

React-router-dom: Clicking on Link adds the route to the Url Link indefinitely

After several attempts, I have managed to implement basic nested-routing with React-router-dom.
Here's the simple project structure:
Here are the relevant files:
App.js
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import ParentComponent from "./Components/nestedComponents/ParentComponent";
import NavBar from "./Components/Shared/NavBar";
function App() {
return (
<div className="App">
<BrowserRouter>
<NavBar />
<Switch>
<Route path="/home" name="Home" component={ParentComponent} />
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
NavBar.js
import React from "react";
import { Link } from "react-router-dom";
export default function NavBar() {
return (
<div>
<Link to={`home/nestedComponentOne`}> Nested Component One </Link>
<Link to={`home/nestedComponentTwo`}> Nested Component Two </Link>
</div>
);
}
ParentComponent.js
import React from "react";
import nestedComponentOne from "./nestedComponentOne";
import nestedComponentTwo from "./nestedComponentTwo";
import { Switch, Route } from "react-router-dom";
export default function ParentComponent() {
return (
<div>
<Switch>
<Route path="/home/nestedComponentOne" component={nestedComponentOne} />
<Route path="/home/nestedComponentTwo" component={nestedComponentTwo} />
</Switch>
</div>
);
}
nestedComponentOne.js
import React from "react";
export default function nestedComponentOne() {
return <div>NESTED COMPONENT 1</div>;
}
nestedComponentTwo.js
import React from "react";
export default function nestedComponentTwo() {
return <div>NESTED COMPONENT 2</div>;
}
So here's the Result:
If I click on nestedComponentOne:
If I click on nestedComponentTwo:
The problem is when I click again on nestedComponentOne (or Two) after the I have clicked it the first time, the route gets added to the url string instead of replacing it:
Some update need for your code.
Working Demo
NavBar.js
Here you forget to add slash / at front to link from root.
<Link to={`/home/nestedComponentOne`}> Nested Component One </Link>
<Link to={`/home/nestedComponentTwo`}> Nested Component Two </Link>
ParentComponent.js
As we removed the Switch from this component, so we need to get the matching information from parent router and pass the path to navigate the corresponding your nested component
export default function ParentComponent({ match }) {
return (
<div>
<Route path={`${match.path}/nestedComponentOne`} component={nestedComponentOne} />
<Route path={`${match.path}/nestedComponentTwo`} component={nestedComponentTwo} />
</div>
);
}
Why don't you try putting all the route in one file. Something like this:
<Route exact path="/home" name="Home" component={ParentComponent} />
<Route path="/home/nestedComponentOne" component={nestedComponentOne} />
<Route path="/home/nestedComponentTwo" component={nestedComponentTwo} />

How to redirect to another class component/Page in ReactJs

How to redirect from one class component to another class component/fresh page in ReactJS.
Currently, I am able to load new components through the link tags in react-router.
but then I want to redirect to another class component just like href in HTML to another fresh page where the previous states will not be available and it's a fresh new class.
Example:- I have 3 Pages
LandingPage
LoginPage
SignupPage
Initially, LandingPage will be opened and after that when I click the respective screen it will open.
How can i load a fresh LoginPage & SignupPage from LandingPage. Both SignupPage and LandingPage have a separate class component to manage the state of that particular screens.
Please share some code references.
Thanks in advance.. :)
If you want to open login or signup page from landing page you can simply call history.push('/login') from landing page component to open login page. history is available in every route so can be called directly.
index.js
import { BrowserRouter, Route,Switch} from 'react-router-dom';
import landingPage from './landingPage';
import login from './login';
import signup from './signup';
render(){
<BrowserRouter>
<Switch>
<Route exact={true} path="/" component={landingPage} />
<Route exact={true} path="/login" component={login} />
<Route exact={true} path="/signup" component={signup} />
</Switch>
</BrowserRouter>
}
//landing page component
landingPage =()=>{
const openLoginPage= () => {
history.push('/login'); //this will open login page on click of login button
}
return(<div>
< button onClick={openLoginPage}>login</button >
</div>)
}
Will it help to reach your idea? I just share you the idea of routing in react using react-router-dom
App.js
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";
import SignUp from "./signUp";
import Login from "./login";
import Landing from "./landing";
class App extends Component {
render() {
return (
<Router>
<div id="container">
<div>
<Link to="/">Landing</Link>
<Link to="/signup">Sign Up</Link>
<Link to="/login">Login</Link>
</div>
<Switch>
<Route exact path="/signup" component={SignUp} />
<Route exact path="/login" component={Login} />
<Route exact path="/" component={Landing} />
</Switch>
</div>
</Router>
);
}
}
export default App;
You have supposedly created your functional component/ class component, you may import and use accordingly
Update for the class components
Once the routed from one component to another component each component will load with its own state and props
I have put here my class components, you have to make sure all App.js, landing.jsx, signUp.jsx and login.jsx are on the same folder location
landing.jsx
import React, { Component } from "react";
class Landing extends Component {
state={}
render() {
return (
<div>
<h1>Landing page</h1>
</div>
);
}
}
export default Landing;
signUp.jsx
import React, { Component } from "react";
class SignUp extends Component {
state={}
render() {
return (
<div>
<h1>Sign Up page</h1>
</div>
);
}
}
export default SignUp;
login.jsx
import React, { Component } from "react";
class Login extends Component {
state={}
render() {
return (
<div>
<h1>Login page</h1>
</div>
);
}
}
export default Login;
Another way is use push method on button click inside class components, and in both cases route should be there
<button onClick={()=> this.props.history.push('/')} ></button>
or
<button onClick={()=> this.props.history.push('/signup')} ></button>

React not rendering Route Components

I am building a consumer facing app with a admin dashboard. I want to keep the routing separate for them and so trying to delegate :-
App.js
import React, {Component} from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
//styles
import './style/bootstrap/bootstrap.scss';
//apps
import Mainapp from './mainapp/Mainapp';
import Admin from './admin/Admin';
const MainappContainer = () => (
<Mainapp />
);
const AdminContainer = () => (
<Admin />
);
class App extends Component{
render(){
return (
<Router>
<Switch>
<Route path="/admin" component={AdminContainer}/>
<Route path="/" component={MainappContainer}/>
</Switch>
</Router>
)
}
}
export default App;
Admin.js
import React, {Component} from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
//styles
import './admin-style.scss';
//layout
import ControlPanel from './component/layout/ControlPanel';
import Navbar from './component/layout/Navbar';
//pages
import Quote from './component/pages/quote/Quote';
class Admin extends Component{
render(){
return (
<div className="adminWrapper">
<ControlPanel />
<section className="viewPanel">
<Navbar />
<Router>
<Route path="/quote" component={Quote}/>
</Router>
</section>
</div>
)
}
}
export default Admin;
However when I hit the URL
http://localhost:3000/admin/quote
it doesn't seem to load the quote component
Quote.js
import React, { Component } from 'react';
class Quote extends Component {
render() {
return (
<div className="float-right pr-3">
<h3>
Quote Page
</h3>
</div>
)
}
}
export default Quote;
When dealing with nested subroutes, the easiest solution is to use match.
path - (string) The path pattern used to match. Useful for building nested
Routes.
url - (string) The matched portion of the URL. Useful for building
nested Links.
By design, components placed inside a Route's component render method are given several additional props from react-router-dom. Among them are history and match. You can leverage these props to either to match against sub routes and/or to control browser history location.
In addition, you only need one instance of BrowserRouter sitting at the top-level of the application, then you can use Switch to optionally render any main or sub routes. And you don't need to use class components unless you're utilizing state and/or a class field.
A very basic, rudimentary working example of your application:
src/components/Admin/index.js
import React from "react";
import { Switch, Link, Route } from "react-router-dom";
import ControlPanel from "../ControlPanel";
import Quote from "../Quote";
// since Admin is placed inside a Route's component render
// method, it has access to history and match
function Admin({ history, match }) {
return (
<div className="adminWrapper">
<ControlPanel />
<section className="viewPanel">
<Link to={`${match.url}/quote`}>View quote</Link>
<br />
<Switch>
<Route exact path={`${match.path}/quote`} component={Quote} />
</Switch>
</section>
<br />
<button type="button" onClick={() => history.goBack()}>
Go Back
</button>
</div>
);
}
export default Admin;
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
import Admin from "./components/Admin";
const linkStyle = {
padding: "0 10px"
};
function App() {
return (
<BrowserRouter>
<Link style={linkStyle} to="/">
Home
</Link>
<Link style={linkStyle} to="/admin">
Admin
</Link>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/" render={() => <h1>Main App</h1>} />
</Switch>
</BrowserRouter>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
Follow the Nested Routing Example
The main changes you need to do are:
1. Remove the <Router></Router> from Admin component and
2. Prepend match.path to "/quotes", like it is done in Topics component in the example. In the example, Topics is a function component so it is receiving match as function parameter. As your Admin component is class component, you can access it as this.props.match in render method.
<Route path={`${this.props.match.path}/quote`} component={Quote}/>
<Route exact path="/admin" component={AdminContainer}/>
<Route exact path="/admin/quote" component={Quote}/>
This won't route you to /admin/quote instead it will route you to /admin/admin/quote.
Since it is inside admin just /quote is enough
<Route path="/admin" component={AdminContainer}/>
<Route path="/quote" component={Quote}/>

I use React Router 4 in React page but I can't see my component in Route path

[
import React, { Component } from "react";
import { BrowserRouter as Router , Route } from "react-router-dom";
const NewRout = () => {
return(
<p> MY ROUTE </p>
);
}
class App extends Component {
render() {
return (
<Router>
<Route path="/signin" Component={NewRout} />
</Router>
);
}
}
export default App;
]1I'm using router in my react page. But I can't see output.
I import BrowserRouter and Route from react-route-dom
and try to show mt component inside the route.but this is not working for me.Please help me how to solve this issue. Thanks
<BrowserRouter><Route path="signin" Component={Signin} /></BrowserRouter>
You have a mistake in your path:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Link } from "react-router-dom";
import "./styles.css";
const Home = () => (
<h1>
Home <Link to="/signin">SING</Link>
</h1>
);
const SingIn = () => (
<h1>
<Link to="/">Home</Link>
This is singin page
</h1>
);
ReactDOM.render(
<div>
<BrowserRouter>
<div>
<Route exact path="/" component={Home} />
<Route path="/signin" component={SingIn} />
</div>
</BrowserRouter>
</div>,
document.getElementById("root")
);
Now locate to http://localhost:port/singin you will see your component.
Note: I added a / before your path. This denotes that you are going to signin from your root that is /.
You need to use a prop called exact which matches for exact Route.
Try this SandBox
https://codesandbox.io/s/moj8kxp0nx

React Router: Render new view without page refresh

Hello! What I'm trying to do is rework my react-router so the NavLink renders a completely new page on click, instead of rendering at the bottom of the div, as shown in the gif above.
Here's the content of my main App.js component:
import React, { Component } from 'react';
import './App.css';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Home from './Home.js';
import About from './About.js';
import September from './September.js';
import Trilogy from './Trilogy.js';
class App extends Component {
render() {
return (
<Router>
<div>
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about/' component={About} />
<Route path='/september/' component={September} />
<Route exact path='/september/trilogy/' component={Trilogy} />
</Switch>
</div>
</Router>
);
}
}
export default App;
The Home component's code, which holds the NavBar that's used in the Home Page.
import React, { Component } from 'react';
import { BrowserRouter as Router, NavLink, Switch, Route } from 'react-router-dom';
import logo from './logo.png';
import About from './About.js';
import September from './September.js';
import Trilogy from './Trilogy.js';
let NavBar = () => {
return (
<div>
<h2 className="container2"><NavLink to='/about/'>About</NavLink> </h2>
<img src={logo} className="somersetLogo" alt="somersetLogo" />
<h2 className="container" >Contact</h2>
</div>
)
}
class Home extends Component {
render() {
return (
<Router>
<div>
<NavBar />
<Switch>
<Route exact path='/about/' component={About} />
</Switch>
</div>
</Router>
)
}
}
export default Home;
Any idea what went wrong? Any help would be appreciated! Thanks!
If you are using react router v4 or above it should be something like this.
import { Link } from 'react-router-dom';
<Link to='/about'>
About
</Link>
Why you are defining router again in Home component which is not needed. Keeping route configuration in App component would be enough. Hope this helps. Happy coding !

Resources