React not rendering Route Components - reactjs

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

Related

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

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>

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>

How to properly dynamically change information displayed in a website based on URL?

I'm new to JavaScript and React. I seem to be stuck on this question, I have found information but I think that this is not what I'm really looking for perhaps someone can shed some light on the matter.
So what I'm really looking for is a way to create a "mold" page of an node/react app that will display changing information based on the URL a user submits. Say for example look at facebook (or even stackoverflow) one click on a profile of friends 'y' then the url changes to facebook.com/friends-y and if we choose another person it then changes. Thus I believe that's how they must know how to fill their template using the info provided from that URL with names pictures etc.
I saw that a blog suggests to use route another suggest using url queries more so (which I don't know how to read them once given or how to render them say such as with a onChange event sort of thing when say you click on something inside the page).
My question is: Are any of this methods useful, should I combine them I seen websites that uses both or is there another industry standard that i haven't found and perhaps comes with react?
Any guidance would be much appreciated.
First of all i assume that you have multiple component and you want to change from one component to another component via url. so you have to install react router dom
npm install --save react-router-dom
and after then import Router, Route, Link, Switch (whatever you want) from react-router-dom and give route to component inside router tag .... i mention below in my code
import React, { Component } from 'react';
import './App.css';
import Login from './component/login';
import User from './component/user';
import Signup from './component/signup';
import Notfound from './component/notfound';
import { BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
const Home = () => (
<div>
<h2>Home</h2>
</div>
);
class App extends Component {
constructor(props){
super(props);
this.state={
loggedIn : false
}
}
render() {
return (
<Router>
<div className="App">
<ul className="nav nav-pills">
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/login">LogIn</Link>
</li>
<li>
<Link to="/signup">Sign Up</Link>
</li>
<li>
<Link to="/user">User</Link>
</li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Route path="/user" component={User} onEnter={this.requireAuth}/>
<Route path="*" component={Notfound} />
</Switch>
</div>
</Router>
);
}
}
export default App;
note : in my code i have total 5 component in my project
Login,
User,
Signup,
NotFound,
Home
for more router information you can check in this site. https://reacttraining.com/react-router/web/example/basic
import React , {Component} from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import App from './Components/Home/App'
import Digital from './Components/DigitalStrat/Digital-Strat';
import ServiceLines from './Components/Serviceline/ServiceLines';
import Operations from './Components/OperationTransformation/Operations-
Transformation';
import WhyUs from './Components/WhyUs/Why-us';
import Mission from './Components/Mission/Mission';
import OurGroup from './Components/OurGroup/OurGroup';
import Team from './Components/Team/Team';
import Projects from './Components/Projects/Projects';
import Research from './Components/Research/Research';
import News from './Components/News/News';
import Locations from './Components/Location/Locations';
import registerServiceWorker from './registerServiceWorker';
import NewsDetails from "./Components/NewsDetails/newsDetails";
import i18n from './js/i18n'
import { sliderArrow } from './js/sliderArrow';
import { menu } from './js/menu';
import {withRouter} from 'react-router';
import Coockies from './Components/Cookies/Cookies';
class ScrollToTop extends Component {
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
window.scrollTo(0, 0)
}
}
render() {
return this.props.children
}
}
export default withRouter(ScrollToTop);
ReactDOM.render(
<BrowserRouter>
<Switch>
<ScrollToTop>
<Route exact path = "/" component = {App} />
<Route exact path='/index.html' component={App}/>
<Route exact path='/Digital-Strategies.html' component={Digital} />
<Route exact path='/Service-Lines.html' component={ServiceLines} />
<Route exact path='/Operations-Transformation.html' component=
{Operations}/>
<Route exact path='/inside-the-company.html' component={WhyUs}/>
<Route exact path='/Mission.html' component={Mission}/>
<Route exact path='/Our-group.html' component={OurGroup}/>
<Route exact path='/Team.html' component={Team}/>
<Route exact path='/Projects.html' component={Projects}/>
<Route exact path ='/Research-Development.html' component = {Research}/>
<Route exact path='/News.html' component={News}/>
<Route exact path='/news-details.html/:slug' component={NewsDetails}/>
<Route exact path='/Locations.html' component={Locations}/>
<Route exact path='/cookies' component={Coockies} />
</ScrollToTop>
</Switch>
</BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
This is the basic way to route the project. Feel free to ask question.
The way to handle routing in React is with React Router.
With this sort of (virtual) routing there are two main ways that routing needs to be handled.
1. The first is by rendering different components when the url changes—for example rendering a <Home/> component for "/" and an <About/> component for "/about".
An example:
import React, { Component } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import Home from "./pages/Home";
import About from "./pages/About";
class App extends Component {
render() {
return (
<Switch>
<Route exact path="/" component={ Home }/>
<Route path="/about" component={ About }/>
</Switch>
)
}
}
export default withRouter(App);
2. The second case, which I believe your question specifically addresses, is rendering the same component with different data depending on the url—for example having a <Profile/> component but changing its data for "/profiles/1" vs "/profiles/2".
An example:
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Profile extends Component {
constructor() {
super();
this.state = {
profileData: {}
}
}
componentDidMount() {
this.fetchData();
}
componentDidUpdate(prevProps) {
const currentId = this.props.match.params.id;
const prevId = prevProps.match.params.id;
if (currentId !== prevId) {
this.fetchData();
}
}
async fetchData() {
const profileId = this.props.match.params.id;
const profileData = await fetch(`http://example.com/api/profiles/${profileId}`);
this.setState({
profileData
});
}
render() {
const { profileData } = this.state;
return (
<div>
<h1>{ profileData.name }</h1>
</div>
)
}
}
export default withRouter(Profile);
Where the containing parent component of <Profile/> has a <Route/> that looks like this:
<Route path="/profiles/:id" component={ Profile }/>
Which is important so that the id is in this.props.match.params.
Note that in the above example the way to check what data to use to populate the view is by checking the :id parameter in the url. Since information about the url is passed to the <Profile/> component as a prop, we can check if the url changes in componentDidUpdate and get new data if there was a change.
Finally, both of these involve a bit of setup with React Router (basically just wrapping your <App/> in a <Router/>) but the documentation should help with that: https://reacttraining.com/react-router/web/guides/quick-start.
Hopefully this helps.

React - inserting variable into Route path

I have an app that I am creating and am wondering how you would insert variables into the <Route path={insert variable here} component={myProfile}> I am trying to create a myProfile page and I am trying to get it so when they click onto the link, it redirects them to http://mywebsite.com/userId but when I try to create a Route with a variable in the path argument, it does not return the component I am trying to render when on that path.
routes.js
import { Meteor } from "meteor/meteor"
import React from "react";
import { withRouter, Switch, BrowserRouter, Route, Redirect, Link } from "react-router-dom";
import Login from "../ui/authentication/Login";
import Signup from "../ui/authentication/Signup";
import Home from "../ui/Home";
import { SubjectRoutes } from "../ui/subjectRoutes/subjectRoutes";
import AddNote from "../ui/AddNote";
import myProfile from "../ui/myProfile";
import NotFound from "../ui/NotFound";
export default class Routes extends React.Component{
renderSubjectRoutes(subjects){
return subjects.map((subject) => {
return <Route key={subject.name} path={subject.path} component={subject.component}/>
})
}
render(){
return (
<div>
<BrowserRouter>
<Switch>
<Login path="/login" />
<Signup path="/signup" />
<Route path="/" component={Home} exact/>
{this.renderSubjectRoutes(SubjectRoutes)}
<AddNote path="/addNote"/>
<myProfile path={Meteor.userId()} /> //<-- Here
<NotFound />
</Switch>
</BrowserRouter>
</div>
)
}
}
Menu.js
import { Meteor } from "meteor/meteor"
import React from "react";
import { withRouter, Link } from "react-router-dom";
import { SubjectRoutes } from "./subjectRoutes/subjectRoutes";
import AddNote from "./AddNote";
class Menu extends React.Component{
renderMenu(items){
return items.map((item) => {
return <p key={item.name}><Link to={item.path}>{item.name}</Link></p>
})
}
render(){
return(
<div>
<h1>Menu</h1>
{this.renderMenu(SubjectRoutes)}
<p><Link to="/addNote">Add a Note</Link></p>
<p><Link to={Meteor.userId()}>My Profile</Link></p>
</div>
)
}
}
export default withRouter(Menu)
You are creating way more work for yourself, and this is the wrong way to add variables to route. What you're looking to do is add params to your route. In your case, you would want it to look something like this.
<Route path="/user/:userId" />
The : is what denotes that it is a parameter, ready to render a path based on the userId. So if you went to route /user/123 - it would be able to render user 123's data.
Here's some documentation to help you out.
https://reacttraining.com/react-router/web/example/url-params

Resources