5

This is my URL in react js

http://localhost:3000/meassger/student/1

I want to extract 1 from the URL if it was a functional component I could have used ```useParams``

I am getting this error TypeError: Cannot read properties of undefined (reading 'params')

 componentDidMount() {
    console.log(this.props.match.params.id, "");
   
    };
vivek kn
  • 107
  • 1
  • 18
  • 45

3 Answers3

4

In functional component, use

const history = useHistory()

const studentId = history?.location?.pathname.split('/')[3]

In class component, use

const studentId = window.location.href.split('/')[3]
Ritik Banger
  • 2,107
  • 5
  • 25
  • 1
    There are specific methods in React for doing this kind of operation, e.g. `withRouter`. You should avoid doing direct manipulation of the window or document (where possible) because the React VDOM does not keep a track of that. – crevulus Apr 12 '22 at 07:10
  • @crevulus The useHistory hook gives you access to the history instance that you may use to navigate. https://v5.reactrouter.com/web/api/Hooks – Ritik Banger Apr 12 '22 at 07:14
  • But this question is about class components and your method for class components is risky. Plus, you linked to react router v5 - in v5 `useHistory` is deprecated in favour of `useNavigation`. – crevulus Apr 12 '22 at 07:16
  • @crevulus Please look here https://stackoverflow.com/questions/24078332/is-it-secure-to-use-window-location-href-directly-without-validation#:~:text=The%20first%20one%2C%20using%20the,of%20user%20input%20as%20well. – Ritik Banger Apr 12 '22 at 07:21
  • that answer is almost 8 years old... React didn't even exist then. In plain JS this method is fine - and it's not the worst thing in the world to do in React. But there is a React way to do things because React has the vdom which it needs to keep track of any and all changes/properties within the application. And using the correct methods, hooks etc. are safer when working in React because of this vdom. By directly interacting with `window.location.href`, you're circumventing the vdom. This should be avoided if at all possible. – crevulus Apr 12 '22 at 07:25
3

You need to wrap it in withRouter - that injects the URL variables into your props.

You can find an example here: https://stackoverflow.com/a/60316195/13063136

The code:

import React from "react";
import { withRouter } from "react-router";

class ShowTheID extends React.Component {

  const { match } = this.props;

  componentDidMount() {
    console.log(match.params.id)
  }

  render() {
    return <div>{match.params.id}</div>;
  }
}

const ShowTheIDWithRouter = withRouter(ShowTheID);

Note: Along with wrapping your component in withRouter you also need to make sure that your route is registered and you have mentioned URL params in your Route path like path="/meassger/student/:id"

crevulus
  • 1,658
  • 12
  • 42
3

Let's assume we have a url like http://localhost:3000/student/:studentId and we need to grab studentId param from this url

In a functional component, we can do it like

import React from 'react';
import { useParams } from 'react-router-dom';

const Student = () => {
    const { studentId } = useParams();
    return (
        <div>StudentId: { studentId }</div>
    );
}
export default Student;

In a class based component, we can do it like

import React, { Component } from 'react';

class Student extends Component {
    render() {
        const { studentId } = this.props.match.params;
        return (
            <div>StudentId: { studentId }</div>
        );
    }
}
export default Student;

Alternatively, you can use withRouter HOC. By doing so, you can also access location and history props.

import React, { Component } from 'react';
import { withRouter } from "react-router";

class Student extends Component {
  render() {
    const { location, history } = this.props;

    return (
      <React.Fragment>
        <div>StudentId: { match.studentId }</div>
        <div>Path: {location.pathname}</div>
      </React.Fragment>
    );
  }
}

const StudentWithRouter = withRouter(Student);
Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22