How render form on new page using React NavLink? - reactjs

I have the following NavLink in my React Sidebar component that successfully links to an add-folder new page; however, I'm unable to render an AddFolder form on this new page (I've successfully tested that the AddFolder form renders in the Sidebar component, but that's not what I want). I've tried numerous things to resolve this, including using "component={AddFolder}", "render={={() => { return }}". Most recently I tried adding an onClick which doesn't work either.
<section className="AddFolder_Section">
<NavLink
className="AddFolder_Button"
tag={Link}
to={'/add-folder'}
type='button'
onClick={() => this.AddFolder}
>
Add Folder
</NavLink>
</section>
Are there pointers that you can give me on what might work here? Thank you.
Here are the entire contents of my sidebar.js file:
import React, { Component } from 'react'
import { NavLink, Route, Link } from 'react-router-dom'
import NotesContext from './notesContext'
import AddFolder from './addFolder'
import './sidebar.css'
class Sidebar extends Component {
static contextType = NotesContext
render() {
let notesContext = this.context
const selectedFolder = this.props.match.params.folder_id || {}
return (
<section className="Sidebar">
{notesContext.folders.map(folder => {
return(
<section key={folder.id} className={(selectedFolder && selectedFolder === folder.id)? "SelectedFolder": "Folder"}>
<NavLink className="Folder_Link"
tag='button'
role='link'
to={'/folder/' + folder.id}>
{folder.name}
</NavLink>
</section>
)
})}
<section className="AddFolder_Section">
<NavLink
className="AddFolder_Button"
tag={Link}
to={'/add-folder'}
type='button'
onClick={() => this.AddFolder}
>
Add Folder
</NavLink>
<Route
path='/add-folder'
render={(props) =>
<AddFolder
{...props}
/>
}
/>
</section>
</section>
);
}
}
export default Sidebar;

As I understand your question: AddFolder is your "form" component.
You need to first import your AddFolder component on the parent component that you want to render the form on.
import AddFolder from '../somePath/AddFolder';
Then on your render() function, place the <Route> and simply render the AddFolder component when you are on the add-folder path. Pass props if needed.
<Route
path='/add-folder'
render={(props) =>
<AddFolder
{...props}
/>
}
/>

It turns out I had a typo in the Route defined in my App.js. I needed 'add-folder' instead of 'add_folder'. Now the Route in App works with the NavLink in Sidebar. Yeah!
Here is the App.js:
import React, { Component } from 'react'
import { Route, Switch } from 'react-router-dom'
import Header from './header.js'
import Main from './main.js'
import MainDetail from './mainDetail.js'
import Sidebar from './sidebar.js'
import SidebarDetail from './sidebarDetail.js'
import NotesContext from './notesContext'
import './App.css'
import config from './config'
import AddFolder from './addFolder'
import AddNote from './addNote'
class App extends Component {
state = {
folders: [],
notes: [],
error: null,
};
setData = (notes, folders) => {
this.setState({
notes,
folders,
error: null
})
}
deleteNote = note_id => {
fetch(config.API_ENDPOINT + "/notes/" + note_id, {
method: 'DELETE',
headers: {
'content-type': 'application/json'
}
})
.then(response => response.json())
.then(result => {
const newNotes = this.state.notes.filter(note => note.id !== note_id)
this.setState({
notes: newNotes
})
})
}
addFolder = (name, id) => {
this.setState({
folders: [...this.state.folders, {name, id}]
})
}
componentDidMount() {
Promise.all([
fetch(config.API_ENDPOINT + "/notes"),
fetch(config.API_ENDPOINT + "/folders")
])
.then(responses => {
return Promise.all(responses.map(function (response) {
return response.json();
}));
})
.then(results => {
this.setData(results[0], results[1])
})
.catch(error => this.setState({ error }))
}
render() {
const contextValue = {
notes: this.state.notes,
folders: this.state.folders,
deleteNote: this.deleteNote,
addFolder: this.addFolder
}
//console.log(this.state.notes)
return (
<NotesContext.Provider value={contextValue}>
<section className="App">
<Switch>
<Route
exact path="/"
component={Header}
/>
<Route
path="/folder/:folder_id"
component={Header}
/>
<Route
path="/note/:note_id"
component={Header}
/>
</Switch>
<section className="Section_Sidebar">
<Switch>
<Route
exact path="/"
component={Sidebar}
/>
<Route
path="/folder/:folder_id"
component={Sidebar}
/>
<Route
path="/note/:note_id"
component={SidebarDetail}
/>
</Switch>
</section>
<section className="Section_Main">
<Switch>
<Route
exact path="/"
component={Main}
/>
<Route
path="/folder/:folder_id"
component={Main}
/>
<Route
path="/note/:note_id"
component={MainDetail}
/>
<Route
path="/add-folder"
component={AddFolder}
/>
<Route
path="/add-note"
component={AddNote}
/>
</Switch>
</section>
</section>
</NotesContext.Provider>
);
}
}
export default App;
This is the updated Sidebar.js:
import React, { Component } from 'react'
import { NavLink, Route, Link } from 'react-router-dom'
import NotesContext from './notesContext'
import AddFolder from './addFolder'
import './sidebar.css'
class Sidebar extends Component {
static contextType = NotesContext
render() {
let notesContext = this.context
const selectedFolder = this.props.match.params.folder_id || {}
return (
<section className="Sidebar">
{notesContext.folders.map(folder => {
return(
<section key={folder.id} className={(selectedFolder && selectedFolder === folder.id)? "SelectedFolder": "Folder"}>
<NavLink className="Folder_Link"
tag='button'
role='link'
to={'/folder/' + folder.id}>
{folder.name}
</NavLink>
</section>
)
})}
<section className="AddFolder_Section">
<NavLink
className="AddFolder_Button"
tag={Link}
to={'/add-folder'}
type='button'
>
Add Folder
</NavLink>
</section>
</section>
);
}
}
export default Sidebar;

Related

Link & useHistory.push from 'react-router-dom' changes URL but Not reloading page

I would like to have a button to redirect to homepage on 404 and errorBoundary pages.
I am getting history object and url changes on button click.
However, it does not reload homepage.
Link & useHistory works perfectly on other pages except these two !
tried Router & BrowserRouter both from 'react-router-dom', but none of them worked.
Any advice ? Thank you !!
versions
react 17.0.2
react-dom 17.0.2
react-router-dom 5.2.0
routes.js
import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
const routes = () => (
<Router history={history}>
<ErrorBoundary>
<Suspense fallback={<Loading />}>
<App />
<Switch>
<Route path="/login" component={Login} />
<Route exact path={['/', '/reserves']} component={ReservesMain} />
<PrivateRoute path="/reserve/:id" component={ReserveMain} />
<PrivateRoute path="/managers" component={ManagersMain} />
<PrivateRoute path="/manager/:id" component={ManagerMain} />
<Route component={NotFound} />
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
);
notFound.js
import { useHistory, Link } from 'react-router-dom';
import Button from '../components/shared/button';
...
export default function NotFound() {
const history = useHistory();
const onRedirect = () => history.push('/');
return (
<div>
<h1>404. Not Found. </h1>
<p>Oops! Something's missing...</p>
<p>The page does not exist or is unavailable.</p>
<Link to={'/'}>redirect button</Link>
<Button name="Go Home" onClick={onRedirect} />
</div>
);
}
errorBoundary.js
import React from 'react';
import { connect } from 'react-redux';
import { useHistory } from 'react-router-dom';
import Button from '../components/shared/button';
const BadRequest = ({ status }) => [
<h1 key="be-1">
{status ? <span>{status}.</span> : null} This page isn't working.
</h1>,
<h2 key="be-2">Your client has issued a malformed or illegal request.</h2>,
<h2 key="be-3">If the problem continues, contact the engineer department.</h2>,
];
const SystemError = ({ status }) => [
<h1 key="se-1">
{status ? <span>{status}.</span> : null} Something went wrong.
</h1>,
<h2 key="se-2">Oops! We're experiencing an internal Server Error.</h2>,
<h2 key="se-3">Please try again later.</h2>,
];
export const ErrorComponents = ({ status }) => {
const history = useHistory();
const onRedirect = () => history.push('/');
return (
<>
<div style={rootStyle}>
<div style={innerStyles}>
{status === 400 ? <BadRequest status={status} /> : <SystemError status={status} />}
<Button name="Go Home" onClick={onRedirect} />
</div>
</>
);
};
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
}
static getDerivedStateFromError(error) {
return { error };
}
componentDidCatch(error, info) {
if (process.env.NODE_ENV === 'development') {
console.log(`error : ${error.name}, message: ${error.message || 'null'}`);
console.log(`info : ${JSON.stringify(info)}`);
}
}
render() {
if (this.state.error) {
return <ErrorComponents status={this.props.asyncApi.status} />;
}
return this.props.children;
}
}
const mapStateToProps = (state) => ({
asyncApi: state.asyncApi,
});
export default connect(mapStateToProps, null)(ErrorBoundary);

Pass state from one component to another stateless component

I tried to summarize my problem in the code below. My real code it is too big, so I developed another similar code in way to solve this problem.
I have a loggin page where the user has to type "True" or "False" to update the state fom this component.
I need to pass this state to the "Route" component, that will verify what page is going to be rendered. If the parameter received from the Login component is "True", then Home page will be rendered. If it is "False" Login page will be rendered.
From my understanding, I have to pass props from childreen to parent component, but I am not being able to solve this problem.
App.jsx (Component)
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import Routes from './Routes'
export default props =>
<BrowserRouter>
<div>
<Routes />
</div>
</BrowserRouter>
Routes.jsx (Component)
import React from 'react'
import { Switch, Route, Redirect} from 'react-router'
import Login from './Login';
import Home from './Home';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
isAuthenticated() ? (
<Component {...props} />
): (
<Redirect to={{pathname: "/login", state: {from: props.location }}} />
)}
/>
)
const Routes = () =>
<Switch>
<PrivateRoute path='/home' component={Home} />
<Route exact path='/login' component={Login} />
<Redirect from='*' to='/home' />
</Switch>
export default Routes;
Home.jsx (Component)
import React, { Component } from 'react'
export default class Home extends Component {
render (){
return (
<h1>This is the HOME page</h1>
);
}
}
Login.jsx (Component)
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import Routes from './Routes'
export default class Login extends Component{
constructor(props){
super(props);
this.state = {
userLoggedIn: false
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
e.preventDefault()
let stateName = e.target.name
let stateValue = e.target.value
console.log(e.target, e.target.value)
this.setState({ [stateName]: stateValue})
}
render(){
console.log('esse estado é',this.state.userLoggedIn)
return(
<div>
<div>This is the Login Page</div>
<label>State Test</label>
<input placeholder="true or false" onChange={e => this.handleChange(e)}></input>
<Link to={{pathname: "/home"}}>
<button >Go To Home Page</button>
</Link>
</div>
)
}
}
What do I expect?
When the user type "True" in the Login page, Home page must be rendered.
When the user type "False" in the Login page, Login page must be rendered.
Here is the working code and codesandbox link
If user enters false, then he will not be redirected as he is already on Login page.
import React, { Component } from "react";
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from "react-router-dom";
function AuthExample() {
return (
<Router>
<div>
<AuthButton />
<ul>
<li>
<Link to="/home">Home Page</Link>
</li>
</ul>
<Route path="/login" component={Login} />
<PrivateRoute path="/home" component={Home} />
</div>
</Router>
);
}
const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true;
setTimeout(cb, 100); // fake async
},
signout(cb) {
this.isAuthenticated = false;
setTimeout(cb, 100);
}
};
const AuthButton = withRouter(({ history }) =>
fakeAuth.isAuthenticated ? (
<p>
Welcome!{" "}
<button
onClick={() => {
fakeAuth.signout(() => history.push("/"));
}}
>
Sign out
</button>
</p>
) : (
<p>You are not logged in.</p>
)
);
function Home() {
return <h3>This is the HOME page</h3>;
}
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
}
class Login extends Component {
state = {
redirectToReferrer: false,
input: ""
};
login = e => {
e.preventDefault();
if (this.state.input === "true") {
fakeAuth.authenticate(() => {
this.setState({ redirectToReferrer: true });
});
} else {
this.setState({ redirectToReferrer: true });
}
};
handleChange = ({ target }) => {
this.setState({ [target.name]: target.value });
};
render() {
let { from } = this.props.location.state || { from: { pathname: "/" } };
let { redirectToReferrer } = this.state;
if (redirectToReferrer) return <Redirect to={from} />;
return (
<div>
<div>This is the Login Page</div>
<label>State Test</label>
<br />
<input
placeholder="true or false"
name={"input"}
value={this.state.input}
onChange={this.handleChange}
/>
<br />
<button onClick={this.login}>Go To Home Page</button>
</div>
);
}
}
export default AuthExample;
Hope that helps!!!

ReactJS - Dynamic Routes

I have these components. I want to turn every <House/> into a dynamic url. For example, when accessing in the browser, http://localhost:3000/houses/house/1
I want to appear the House 1.
The other things in the application are working fine. I just want to solve this problem of implementing dynamic routes.
Router Component
import React from 'react';
import { BrowserRouter as Router, Route, NavLink } from 'react-router-dom'
import App from './App'
import Houses from './Houses'
export default props => (
<Router>
<Route exact path='/' render={() => <App />} >
<Route exact path='/houses' render={() => <Houses />} />
</Route>
</Router>
)
Houses Component
import React, { Component } from 'react'
import House from './House'
var data = require('./db.json');
class Houses extends Component {
constructor(props) {
super(props);
this.state = {
currentHouse: []
};
}
componentDidMount() {
this.setState({
currentHouse: data[0]
})
}
render() {
const {currentHouse} = this.state;
return (
<div className="content house">
<ul>
{currentHouse.photos && currentHouse.photos.map((photo, index) => {
return(
<House photo={photo} key={index}/>
)
})}
</ul>
</div>
)
}
}
export default Houses
House Component
import React from 'react';
function House(prop) {
return (
<li><img src={`/images/${prop.photo}`}/></li>
);
}
export default House;
<Route exact path='/houses/:id' render={(props) => <House {...props} />} />
and inside House component retrieve the id:
prop.match.params.id
Ref: https://scotch.io/courses/using-react-router-4/route-params

Problems navigating to URL like "/annotationsList/:id"

I am trying to navigate from a List of annotations to an concrete Annotation using a Link from React Router. But It didn't render the component.
So, I have an AnnotationList in where I have all the annotations. Each annotation have a "". In my Container.js I have declared the Route like this:
<Route path="/annotationList/annView/:id" component={annView} />
And in the same Container I have the component annView:
const annView = ({ match }) => {
const { id } = match.params;
console.log(id);
return(
<AnnotationView id={id} />
)
}
When I click on the Link, the URL change to the correct one, but it didn't render anything. What Am I doing wrong?
I paste the complete code of these two js files if it helps.
Container.js
import React from 'react';
import { Route, Switch, withRouter, Link } from "react-router-dom";
import ProductList from './List/ProductList';
import CustomersList from './List/CustomersList';
import AppointmentsList from './List/AppointmentsList';
import AnnotationList from './List/AnnotationList';
import AddProduct from './Post/AddProduct';
import '../styles/App.css';
import AnnotationView from './Item/AnnotationView';
function Container({ location }) {
return (
<div>
<Switch location={location}>
<Route path="/productsList" component={ProductList} />
<Route path="/customersList" component={CustomersList} />
<Route path="/appointmentsList" component={AppointmentsList} />
<Route path="/annotationList" component={AnnotationList} />
<Route path="/annotationList/annView/:id" component={annView} />
<Route path="/addProduct" component={AddProduct} />
</Switch>
</div>
);
}
const annView = ({ match }) => {
const { id } = match.params;
console.log(id);
return(
<AnnotationView id={id} />
)
}
export default withRouter(Container);
import React, { Component } from 'react';
import { Table } from 'reactstrap';
import { Link } from 'react-router-dom';
import AnnotationView from '../Item/AnnotationView';
class AnnotationList extends Component {
constructor(props) {
super(props);
this.state = {
annotations: [],
isLoading: false
}
}
componentDidMount() {
this.setState({isLoading: true});
fetch('http://localhost:8080/annotations')
.then(response => response.json())
.then(data => this.setState({annotations: data, isLoading: false}));
}
render() {
const { annotations, isLoading } = this.state;
if(isLoading) {
return <p>Loading...</p>;
}
return(
<div>
<h2>Anotaciones</h2>
<div className="form-group">
<input type="date"/>
</div>
<Table>
{annotations.map((ann) =>
<div>
<tr>
<Link to={`/annotationsList/annView/${ann.id}`}>
<th>{ann.name}</th>
</Link>
</tr>
<tr>
<td>{ann.text}</td>
</tr>
</div>
)}
</Table>
</div>
)
}
}
export default AnnotationList;
Thanks in advance.
You have a typo in your Link component.
You're trying to match this route
<Route path="/annotationList/annView/:id" component={annView} />
but your Link has annotations with an s
/annotationsList/annView/anythingHere
You have to change your Link Component to this:
<Link to={`/annotationList/annView/${ann.id}`}>
<th>{ann.name}</th>
</Link>
Note: I would still recommend that every time you have similar routes you use exact on at least 1 of them to let React Router know how to differentiate between the routes.
function Container({ location }) {
return (
<div>
<Switch location={location}>
<Route path="/productsList" component={ProductList} />
<Route path="/customersList" component={CustomersList} />
<Route path="/appointmentsList" component={AppointmentsList} />
<Route exact path="/annotationList" component={AnnotationList} />
<Route path="/annotationList/annView/:id" component={annView} />
<Route path="/addProduct" component={AddProduct} />
</Switch>
</div>
);
}

React Router Pass Param to Component

const rootEl = document.getElementById('root');
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path="/">
<MasterPage />
</Route>
<Route exact path="/details/:id" >
<DetailsPage />
</Route>
</Switch>
</BrowserRouter>,
rootEl
);
I am trying access the id in the DetailsPage component but it is not being accessible. I tried
<DetailsPage foo={this.props}/>
to pass parameters to the DetailsPage, but in vain.
export default class DetailsPage extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="page">
<Header />
<div id="mainContentContainer" >
</div>
</div>
);
}
}
So any idea how to pass the ID on to the DetailsPage ?
I used this to access the ID in my component:
<Route path="/details/:id" component={DetailsPage}/>
And in the detail component:
export default class DetailsPage extends Component {
render() {
return(
<div>
<h2>{this.props.match.params.id}</h2>
</div>
)
}
}
This will render any ID inside an h2, hope that helps someone.
If you want to pass props to a component inside a route, the simplest way is by utilizing the render, like this:
<Route exact path="/details/:id" render={(props) => <DetailsPage globalStore={globalStore} {...props} /> } />
You can access the props inside the DetailPage using:
this.props.match
this.props.globalStore
The {...props} is needed to pass the original Route's props, otherwise you will only get this.props.globalStore inside the DetailPage.
Since react-router v5.1 with hooks:
import { useParams } from 'react-router';
export default function DetailsPage() {
const { id } = useParams();
}
See https://reacttraining.com/blog/react-router-v5-1/
Use render method:
<Route exact path="/details/:id" render={(props) => (
<DetailsPage id={props.match.params.id}/>
)} />
And you should be able to access the id using:
this.props.id
Inside the DetailsPage component
In addition to Alexander Lunas answer ...
If you want to add more than one argument just use:
<Route path="/details/:id/:title" component={DetailsPage}/>
export default class DetailsPage extends Component {
render() {
return(
<div>
<h2>{this.props.match.params.id}</h2>
<h3>{this.props.match.params.title}</h3>
</div>
)
}
}
Use the component:
<Route exact path="/details/:id" component={DetailsPage} />
And you should be able to access the id using:
this.props.match.params.id
Inside the DetailsPage component
This is for react-router-dom v6 (I highly suggest using functional components for this)
It's somewhat painful for react-router-dom to keep changing syntax and rules. But here goes nothing.
You can use both useParams and useSelector to solve this
import { useParams } from 'react-router';
import { useSelector } from 'react-redux';
const Component = () => {
const { id } = useParams(); //returns the :id
const page = useSelector((state) => state.something[id]); //returns state of the page
return <div>Page Detail</div>;
}
export default Component;
BUT, the problem persist when you also have an action creator and you want to pass it as a props in connect function
export const connect(mapStateToProps, mapDispatchToProps)(Component)
since we are using useParams, it won't be passed to mapStateToProps that we created
const mapStateToProps = (state, ownProps) => {
console.log(ownProps) //wont recognize :id
//hence
return {
someReducers: state.someReducers[id] //would return an error: 'id' is not defined
};
};
on the other hand, you can't entirely ignore the connect function since you need mapDispatchToProps to work with your component.
The workaround to this is to create a Higher Order Component withRouter function yourself. This was a deprecated react-router-dom helper.
//make this
import { useParams, useLocation, useNavigate } from 'react-router';
import { connect } from 'react-redux';
import { yourActionCreator } from '../actionCreator';
const withRouter = (Child) => {
return (props) => {
const location = useLocation();
const navigation = useNavigate();
const params = useParams();
return (
<Child
{...props}
params={params}
navigate={navigate}
location={location}
/>
);
};
};
const Component = () => {
// your component...
return <div> Page Detail </div>
};
export mapStateToProps = (state, ownProps) => {
console.log(ownProps) // would contain the :id params
return {
//something
}
};
const mapDispatchToProps = {
yourActionCreator
}
export withRouter(connect(mapStateToProps, mapDispatchToProps)(Component));
Here's typescript version. works on "react-router-dom": "^4.3.1"
export const AppRouter: React.StatelessComponent = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/problem/:problemId" render={props => <ProblemPage {...props.match.params} />} />
<Route path="/" exact component={App} />
</Switch>
</BrowserRouter>
);
};
and component
export class ProblemPage extends React.Component<ProblemRouteTokens> {
public render(): JSX.Element {
return <div>{this.props.problemId}</div>;
}
}
where ProblemRouteTokens
export interface ProblemRouteTokens {
problemId: string; }
Another solution is to use a state and lifecycle hooks in the routed component and a search statement in the to property of the <Link /> component. The search parameters can later be accessed via new URLSearchParams();
<Link
key={id}
to={{
pathname: this.props.match.url + '/' + foo,
search: '?foo=' + foo
}} />
<Route path="/details/:foo" component={DetailsPage}/>
export default class DetailsPage extends Component {
state = {
foo: ''
}
componentDidMount () {
this.parseQueryParams();
}
componentDidUpdate() {
this.parseQueryParams();
}
parseQueryParams () {
const query = new URLSearchParams(this.props.location.search);
for (let param of query.entries()) {
if (this.state.foo!== param[1]) {
this.setState({foo: param[1]});
}
}
}
render() {
return(
<div>
<h2>{this.state.foo}</h2>
</div>
)
}
}
FOR version 6 ( 2022 )
Note: using useParams you can easily get your params in your component.
look at the example below
import React from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import Home from "./compo/home";
import About from "./compo/about";
import Login from "./compo/login";
import "./styles.css";
const App = () => {
return (
<Router>
<div className="container">
<Link to="/home">Home</Link>
<Link to="/about">About</Link>
<Link to="/login">Login</Link>
</div>
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
<Route path="/login/:name" element={<Login />} />
</Routes>
</Router>
);
};
export default App;
Login Component
import { useParams } from "react-router-dom";
const Login = () => {
let { name } = useParams();
return <h1>i am {name ? <b>{name}</b> : "login"}</h1>;
};
export default Login;
if you are using class component, you are most likely to use GSerjo suggestion. Pass in the params via <Route> props to your target component:
exact path="/problem/:problemId" render={props => <ProblemPage {...props.match.params} />}
In the latest version of (react-router-dom#6.3.0), you can do it like this:
<Route path="path" element={<YourComponent type="simple" />} />
Here, type is the input passed to YourComponent
I was working on react-router-dom version 6.3.0 and above solution didn't resolve my problem. Then I use something like this and it worked:
<Route exact path='/payment-status/:userId/:orderId' element={<PaymentStatus/>}/>
And on PaymentStatus.js page I did like this:
import { useParams } from 'react-router-dom'
export const PaymentStatus = () => {
let {userId, orderId}=useParams()
return (
<div>
<h2>order ID : {orderId}</h2>
<h2>user ID : {userId}</h2>
</div>
)
}
It worked for me. I hope it may help someone. Thanks!
try this.
<Route exact path="/details/:id" render={(props)=>{return(
<DetailsPage id={props.match.params.id}/>)
}} />
In details page try this...
this.props.id
Simple example with Class, HoC and Router v5
package.json
"react-router-dom": "5.3.1",
"react-router": "5.3.1",
"#types/react-router-dom": "5.3.3",
// YourComponent.tsx
import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
export interface PathParams {
id: string;
}
export interface Props extends RouteComponentProps<PathParams> {}
export interface State {}
class YourComponent extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {};
console.log(props.match.params) // { id: 1 }
// TypeScript completions
console.log(props.match.params.id) // 1
}
render() {
return <></>;
}
}
export default withRouter(YourComponent);
// App.tsx
import './App.css';
import React from 'react';
import { Route, Switch, Router } from 'react-router-dom';
import YourComponent from './YourComponent';
function App(): JSX.Element {
return (
<Router>
<Switch>
<Route
path="/details/:id"
component={() => <YourComponent />}
/>
</Switch>
</Router>
);
}
export default App;

Resources