Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-router-v6 access a url parameter

How can i access url parameter in my react component ?

App.js

<Route path="/question/:id" element={<QuestionView />} />

QuestionView.js

class QuestionView extends React.Component {     
    render() {
          const { questions, users } = this.props;
          const {id} = ??? 
like image 261
ziad hany Avatar asked Nov 18 '25 22:11

ziad hany


2 Answers

Issue

In react-router-dom v6 the Route components no longer have route props (history, location, and match), and the current solution is to use the React hooks "versions" of these to use within the components being rendered. React hooks can't be used in class components though.

To access the match params with a class component you must either convert to a function component, or roll your own custom withRouter Higher Order Component to inject the "route props" like the withRouter HOC from react-router-dom v5.x did.

Solution

I won't cover converting a class component to function component. Here's an example custom withRouter HOC:

const withRouter = WrappedComponent => props => {
  const params = useParams();
  // etc... other react-router-dom v6 hooks

  return (
    <WrappedComponent
      {...props}
      params={params}
      // etc...
    />
  );
};

And decorate the component with the new HOC.

export default withRouter(Post);

This will inject a params prop for the class component.

this.props.params.id
like image 77
Drew Reese Avatar answered Nov 21 '25 14:11

Drew Reese


HOC withRouter TypeScript version with generic Params

withRouter.tsx

import { ComponentType } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';

export interface WithRouterProps<T = ReturnType<typeof useParams>> {
  history: {
    back: () => void;
    goBack: () => void;
    location: ReturnType<typeof useLocation>;
    push: (url: string, state?: any) => void;
  }
  location: ReturnType<typeof useLocation>;
  match: {
    params: T;
  };
  navigate: ReturnType<typeof useNavigate>;
}

export const withRouter = <P extends object>(Component: ComponentType<P>) => {
  return (props: Omit<P, keyof WithRouterProps>) => {
    const location = useLocation();
    const match = { params: useParams() };
    const navigate = useNavigate();

    const history = {
      back: () => navigate(-1),
      goBack: () => navigate(-1),
      location,
      push: (url: string, state?: any) => navigate(url, { state }),
      replace: (url: string, state?: any) => navigate(url, {
        replace: true,
        state
      })
    };

    return (
      <Component
        history={history}
        location={location}
        match={match}
        navigate={navigate}
        {...props as P}
      />
    );
  };
};

MyClass.tsx

import { Component } from 'react';

import { withRouter, WithRouterProps } from './withRouter';

interface Params {
  id: string;
}

type Props = WithRouterProps<Params>;

class MyClass extends Component<Props> {
  render() {
    const { match } = this.props;
    console.log(match.params.id); // with autocomplete
    return <div>MyClass</div>;
  }
}

export default withRouter(MyClass);
like image 45
egor.xyz Avatar answered Nov 21 '25 13:11

egor.xyz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!