I'm creating a personal website to train with React and i have been stuck since a couples of days to render a component with React Router like i will render a blog post when i click on the card.
Eveytime i click on the card instead i got the correct data but it's om the bottom of the main page and i would like to open it dynamically on a new page, like if i click on an article of a blog or a news.
My card component
render() {
const { match } = this.props;
const { data, value } = this.state;
return (
<>
<div>
{data.map((job, id) => (
<div key={id}>
<div key={job._id} className="blog-card">
<div className="meta">
<div className="photo">
<img src={job.img} alt="logo" />{" "}
</div>
</div>
<div className="description">
<p> {job.description}</p>
<p className="read-more">
<p>{job.location}</p>
<p>
<span className="apply-job">
{" "}
<Link
className="link-apply"
to={{
pathname: `${match.url}/${job._id}`,
state: job
}}
>
go to {job.workplace_name}
</Link>{" "}
</span>
</p>
</p>
</div>
</div>
</div>
))}
</div>
}
<Route path={`${match.path}/:_id`} component={Articles} />
</>
);
}
}
When i click on go to {job.workplace_name} i would like to render the component below on a new page and not under my card component
const Articles = ({ location }) => (
<div>
<h1>Hello</h1>
<h1>{location.state.workplace_name}</h1>
<h2>{location.state.position_name}</h2>
<h2>{location.state.description}</h2>
<h2>{location.state.Compensation}</h2>
</div>
)
export default Articles;
When you code your app with react-router you should have a top-level component that is in charge of deciding which screen to print based on the url you are visiting.
It should look like this
import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from "react-router";
const App = () => (
<Switch>
<Route exact path="/invoices/dashboard" component={Dashboard} />
<Route path="/invoices/:id" component={Invoice} />
</Switch>
);
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
el
);
The Switch component will render only the first Route that matches the current URL.
If you don't use it, every route that match will be rendered.
The is useful at the top level to avoid having two screens at the same time (kinda like your issue).
Your biggest issue is that you put the route responsible for the display of a blog page inside your card component.
Your component hierarchy:
Router
└ App
└ Route+Home (maybe)
└ Card
└ Route+Articles
What it should be instead:
Router
└ App
└ Switch
├ Route+Home (maybe)
│ └ Card
└ Route+Articles
Also when you new to change the location (url) you can use the Link component as you did, or use history props that you get from the Route component.
In the example above, Dashboard and Invoice get the "history" property.
history.push(path) will simulate navigation
history.replace(path) will simulate redirection.
and there's more https://reacttraining.com/react-router/core/api/history
So presumably, you have an index.js file that looks like this or should look like this where you added <BrowserRouter> in accordance to the solution:
import { BrowserRouter } from "react-router-dom";
import { Route, Switch } from "react-router";
const App = () => (
<Switch>
<Route exact path="/invoices/dashboard" component={Dashboard} />
<Route path="/invoices/:id" component={Invoice} />
</Switch>
);
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
el
);
But, what if your index.js file looked like this instead:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import reduxThunk from "redux-thunk";
import App from "./components/App";
import reducers from "./reducers";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducers,
composeEnhancers(applyMiddleware(reduxThunk))
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector("#root")
because you created an index.js file that is at the top-level of your component hierarchy and then an App.js file, that looks like this:
import React from "react";
import { Route } from "react-router-dom";
import Dashboard from "./invoices/Dashboard";
import Invoice from "./invoices/Invoice";
import Header from "./Header";
const App = () => {
return (
<div className="ui container">
<div>
<Header />
<Route exact path="/invoices/dashboard" component={Dashboard} />
<Route path="/invoices/:id" component={Invoice} />
</div>
</div>
);
};
export default App;
In such a case, you can use the exact keyword on all your Routes and encapsulate it all inside of <BrowserRouter> and ensure you have that encapsulated in <div>s like so:
import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Dashboard from "./invoices/Dashboard";
import Invoice from "./invoices/Invoice";
import Header from "./Header";
const App = () => {
return (
<div className="ui container">
<BrowserRouter>
<div>
<Header />
<Route exact path="/invoices/dashboard" component={Dashboard} />
<Route exact path="/invoices/:id" component={Invoice} />
</div>
</BrowserRouter>
</div>
);
};
export default App;
Related
I'm coming back to you after a problem I'm having with redirects in React, I've decided to resume my project from 0 and I'm still having the same problem..
When I request this page http://localhost:3000/profil I am automatically redirected to this same page with a slash at the end of the url, e.g. http://localhost:3000/profil/.
Why does the / appear automatically at the end of the url http://localhost:3000/profil/? I'm not asking anywhere.
For the test, the Profil page and the Home page are exactly the same and should return the same image, except that only the Home page returns the image.
Here is the code I am using
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './styles/index.scss'
ReactDOM.render(
<App />,
document.getElementById('root')
);
src/App.js
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import Routes from './components/Routes';
const App = () => {
return (
<div>
<BrowserRouter>
<Routes />
</BrowserRouter>
</div>
)
};
export default App;
src/components/Routes/index.js
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from '../../pages/Home';
import Panier from '../../pages/Panier';
import Profil from '../../pages/Profil';
const index = () => {
return (
<Routes>
<Route path='/' element={<Home />} />
<Route path='/profil' element={<Profil />} />
<Route path='/mes-paniers' element={<Panier />} />
<Route path='*' element={<Home />} />
</Routes>
)
};
export default index;
src/pages/Profil
import React from 'react';
const Profil = () => {
return (
<div className="profil-page">
<div className="log-container">
<div className="img-container">
<img src="./img/log.svg" alt="pic-profil" />
</div>
</div>
</div>
)
};
export default Profil;
The Home page looks like the Profil page,
src/pages/Home
import React from 'react';
const Home = () => {
return (
<div className="profil-page">
<div className="log-container">
<div className="img-container">
<img src="./img/log.svg" alt="pic-profil" />
</div>
</div>
</div>
);
};
export default Home;
The image is not found on "/profil/" while on "/home" it is displayed.
I don't understand where the problem comes from.
The problem seems solved to me. I had to reset the default settings of Google Chrome. I can now load my page /profil and no longer /profil/!
EDIT :
It still doesn't work on Brave browser. Can't get just the url http://localhost:3000/profil . It always sends me /profil/.
Unable to see the header text returned in my Home and Tutorials page in my react hooks site. Below is my App.js, Navigation.js and Home.js. Could someone please advise about the problem here.
App.js
import React from 'react';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import './App.css';
import Home from "./components/Home";
import Tutorials from "./components/Tutorials";
import Navigation from './components/Navigation';
function App() {
return (
<BrowserRouter>
<Navigation>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/tutorials" component={Tutorials} />
</Switch>
</Navigation>
</BrowserRouter>
);
};
export default App;
Navigation.js
import React from 'react';
import { NavLink} from 'react-router-dom';
const Navigation = () => {
return (
<div className="App">
<div className="wrapper">
<div id="wrap">
<nav className="siteNavigation_nav_links">
<div className="row" ></div>
<div className="main_links_nav">
<NavLink className="mob_link" to="/">Home</NavLink>
<NavLink className="mob_link" to="/tutorials">Tutorials</NavLink>
</div>
</nav>
</div>
</div>
</div>
)
}
export default Navigation;
Home.js
import React from 'react';
const Home = () =>{
return (
<div className="App">
<h1>This is Home Page !</h1>
</div>
)
}
export default Home;
Tutorials.js
import React from 'react';
const Tutorials = () =>{
return (
<div><h1>This is Tutorials Page !</h1></div>
)
};
export default Tutorials;
Navigation is a Navbar component. And you want it everywhere on the site.
So, you can easily do it by using it outside the scope of the Switch component.
In doing so, it will render all over your screens.
<BrowserRouter>
<Navigation />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/tutorials" component={Tutorials} />
</Switch>
</BrowserRouter>
Hi i am new developer in ReactJS. I have a problem and want to learn how to make routing for dashboard. My root component is App component and it calls only dashboards of my pages. But I want to call different components inside of dashboard such as Login , Register etc. When I use "Link" in anywhere, How can I do this ? Could you help me at this issue?
index.tsx for BrowserRouter
import {BrowserRouter} from "react-router-dom";
const app =<App /> ;
const container = (
<>
<BrowserRouter>
{app}
</BrowserRouter>
</>
);
my router App.tsx component:
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Switch>
<Route path="/Login" exact component={LoginDash}></Route>
<Route path="/" exact component={LoginDash}></Route>
</Switch>
</div>
);
}
}
export default App;
My dashboard LoginDash.tsx:
import {BrowserRouter as Router, Route,Switch} from "react-router-dom"
import LoginPart from "../../components/login/left/LoginPart";
import RegisterPart from "../../components/login/left/RegisterPart";
import AnitamionPart from '../../components/login/right/AnimationPart';
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Router>
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</Router>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
First of all, you only need to use one instance of BrowserRouter in your App, Since you already wrap App component with BrowserRouter that would be enough
Secondly, if you specify exact attribute on Routes, no nested Routes will ever match. Make sure you don't use Route with exact prop if the component has any nested Route defined
Lastly, you only need to render LoginDash on / route, /Login handling can be done separately as a nested Route
Update your individual components like below
import {BrowserRouter} from "react-router-dom";
// Do not render app as a constant separetely,
const container = (
<>
<BrowserRouter>
<App />
</BrowserRouter>
</>
);
import { Route, Switch } from "react-router-dom";
import LoginDash from "../containers/login/LoginDash"
class App extends Component {
render() {
return (
<div className="App">
<Route path="/" component={LoginDash}></Route>
</div>
);
}
}
export default App;
export const Login = () => {
return (
<div className="login-container">
<div className="row login-row" >
<div className="login-left-part" >
<Switch>
<Route exact path = "/Login" component={LoginPart}></Route>
<Route exact path = "/Register" component={RegisterPart}></Route>
</Switch>
</div>
<div className=" login-right-part" >
<AnitamionPart></AnitamionPart>
</div>
</div>
</div>
)
}
export default Login;
Working demo
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}/>
[
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