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.
To get the query parameter from a above url, we can use the useLocation() hook in react router v5. In the above code, we first imported the useLocation() hook from the react-router-dom package and invoked it inside the Items functional component then we parsed the query param data using the new URLSearchParams().
Use the useParams() hook to get the ID from a URL in React, e.g. const params = useParams() . The useParams hook returns an object of key-value pairs of the dynamic params from the current URL that were matched by the Route path. Copied!
Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don't work inside classes — they let you use React without classes. (We don't recommend rewriting your existing components overnight but you can start using Hooks in the new ones if you'd like.)
//use useParams
import { useParams } from 'react-router-dom';
const params = useParams()
// yuo can find all params from here
console.log(params)
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
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);
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.
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