18

What would be the correct approach to reading URI parameters from a functional React component?

In JavaScript, if the component is a direct child of a Switch, we could do:

function MyComponent(props) {
    const query = props.location.search;
    // ...
}

If the component is not a direct child of a Switch, we could use a class:

class MyComponent extends Component<RouteComponentProps> {
    render() {
        const query = this.props.location.search;
        // ...
    }
}

export default withRouter(MyComponent);

What about a functional component in strict TypeScript?

We want the location property (and any other, if there are more) to be available and predefined by some interface or type, but supplied by React, not the user of the component. An ugly hack would be to define the interface ourselves and then expect it to actually be that way.

Snackoverflow
  • 5,332
  • 7
  • 39
  • 69

4 Answers4

18
//use useParams 
import { useParams } from 'react-router-dom';

const params = useParams()

// yuo can find all params from here
console.log(params)
Kasujja Muhammed
  • 422
  • 6
  • 11
  • While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please [include an explanation for your code](https://meta.stackexchange.com/q/114762/269535), as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. You can use the [edit] button to improve this answer to get more votes and reputation! – Brian Tompsett - 汤莱恩 Apr 18 '21 at 09:31
10

As Domino987 said in their answer, the solution is to simply extend the props interface:

import * as React from "react";
import {withRouter, RouteComponentProps} from "react-router";

function MyComponent(props: MyComponentProps) {
    const query = props.location.search;

    return <span>Query: {query}, myField: {props.myField}</span>;
}

interface MyComponentProps extends RouteComponentProps {
    myField: string;
}

export default withRouter(MyComponent);
Snackoverflow
  • 5,332
  • 7
  • 39
  • 69
  • const query = props.match.params.id ==> id is my query param. it accessible in functional component. Thanks a lot; – gnganapath Aug 13 '20 at 23:57
  • Just realized, react16.13 can map in Route the in child fuctional componet we pass props and get the props.match.params.{yourVarble}. It's working – gnganapath Aug 14 '20 at 00:16
7

If you wrap your component (functional or class) in withRouter, your props extend the RouteComponentProps from react-router, which can be corretly set up, just as you did in the seconds example. To access the correct params, you have to extend the props like this:

RouteComponentProps<{ id?: string; }>

This will let typescript know, that you have a match props with an field id, which is optional. You can now access them type safe with props.match.params.id. You can also extend that, to fit your other parameters. Hope this helps. Happy coding.

Domino987
  • 8,475
  • 2
  • 15
  • 38
  • I have found the solution. Now when I am reading this, I believe it points somewhat to the same direction. The key is to extend your interface with `RouteComponentProps` and it seems to work. Though, I don't actually understand the `id?: string` part. Is that some property that is missing by default from `RouteComponentProps` interface? That's why we need to add it manually? – Snackoverflow Aug 01 '19 at 15:50
  • 1
    Because you can create a route like you want to. Since the match params can be anything you want like : , you have to tell typescript, what you set it to. It could also be abalyticID, or selectedAnalytic. – Domino987 Aug 01 '19 at 15:52
  • Ahhh, yes. I just read about `match` from https://reacttraining.com/react-router/core/api/match Did not know about it before. – Snackoverflow Aug 01 '19 at 16:01
6

For Functional component, use below code

Include:

import { BrowserRouter as Router, Switch, Route, Redirect, useLocation
} from 'react-router-dom'

Define function in your functional component:

const useQuery= () => {
       return new URLSearchParams(useLocation().search);
}

Call function:

let query = useQuery();

Get the query get parameters:

console.log("Get data==>",query.get('logout'));
URL: http://localhost:8080/login?logout=false

Output:

Get data==> false
Jin Lee
  • 3,194
  • 12
  • 46
  • 86
Vinay Joshi
  • 61
  • 1
  • 1