I have an app that uses a react-router-config and uses a wrapper component to redirect unauthenticated users.
I have some functionality that requires the use of the route /tasks/:id but I am unable to access the :id value to perform the necessary task lookup.
My routes.js:
import React from "react";
...
const Tasks = React.lazy(() => import("./Components/Tasks"));
...
const routes = [
{
path: "/tasks/edit/:id",
name: "View Task",
component: Tasks
}
...
];
export default routes;
Then I have AuthenticatedRoute.js
:
import React from "react";
import { Route, Redirect } from "react-router-dom";
export default function AuthenticatedRoute({
component: C,
appProps,
...rest
}) {
return (
<Route
{...rest}
render={props =>
appProps.isAuthenticated ? (
<C {...props} {...appProps} />
) : (
<Redirect
to={`/login?redirect=${props.location.pathname}${props.location.search}`}
/>
)
}
/>
);
}
and in the App.js:
import React, { useState, useEffect } from "react";
import { BrowserRouter, Switch, withRouter } from "react-router-dom";
import AuthenticatedRoute from "./components/AuthenticatedRoute/AuthenticatedRoute";
import routes from "./routes";
function App(props) {
...
return (
<BrowserRouter>
<React.Suspense fallback={loading()}>
<Switch>
{routes.map((route, idx) => {
return route.component ? (
<AuthenticatedRoute
key={idx}
path={route.path}
exact={route.exact}
name={route.name}
appProps={props}
component={props => <route.component {...props} />}
/>
) : null;
})}
</Switch>
...
</React.Suspense>
</BrowserRouter>
Finally I have my Tasks.js:
import React, { useState, useEffect } from "react";
...
function Tasks(props) {
useEffect(() => {
onLoad();
}, []);
const onLoad = async () => {
console.log(JSON.stringify(props.match.params));
};
...
Browsing to localhost:3000/tasks/1. props.match.params
is empty in every component up the chain. props.match.params.id
is undefined
. I have also tried match with {match.params.id}
but that is also undefined at every component.
I can see props.location.pathname
but that is the full path and I would have to manually get the last segment. I can't get it to automatically grab the :id
from the url.
EDIT Turns out my example was too simplified, which actually helped me identify the issue. In my previous version when I had the route:
{
path: "/tasks/:id",
name: "View Task",
component: Tasks
}
everything actually works fine using useParams
I am able to get the :id
value. What I actually have in my app and what seems to be breaking it is adding an additional directory to the path:
{
path: "/tasks/edit/:id",
name: "View Task",
component: Tasks
}
I am not sure how this makes a difference, but having the extra /edit
seems to break the useParams
react-router-dom
provides some handy hooks. In your case, I'd suggest useParams()
(link to docs)
import { useParams } from 'react-router-dom';
function MyComponent {
let { id } = useParams();
return (<p>{id}</p>);
}
I'd also probably opt for not using withRouter
if you will be using the hooks provided by React Router
Martins answer is correct and works for functional components. I had the same problem, however I was using a class component (class Company extends Component) and Martins answer did not work for that case. If you have a class component you can do:
import { withRouter } from 'react-router-dom'
class MyComponent extends React.Component {
componentDidMount() {
// here you have the id
const id = this.props.match.params.id;
}
}
export default withRouter(MyComponent);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With