React Router Hook => useParam() (now w/ Typescript)
Tags: react, typescript, javascript
Published: 2021-04-08 21:33:28

While working on a project I needed to get some information out of the URL in the browser. Using the URL to declare what to display is a common situation for frontend, client-side rendering. For example, grabbing an ID or username to send to the backend which is the situation for my current project. 

I was using class-based React components when I began learning React. Six months later I'm learning the ins and outs of functional components with Hooks to maintain necessary stateful logic without all the extra lifecycle methods. This learning led me to discover the [Hooks of React Router](https://reactrouter.com/web/api/Hooks). 

___

```javascript
<Route path={'/quizzes/:id'} render={props => <Quiz {...props}} />

class Quiz extends Component {
   this.state = {
      //necessary state values here
   }

   componentDidMount {
      api.getQuiz(props.match.params.id).then(data =>
         // logic
   )
}
``` 

Here's a code snippet from a project I worked on when I first started with React. This `Route Path` component has parameters that I want to use. While using the render method of Route, I have to destructure or "spread" props inside the component to gain access to the [match object](https://reactrouter.com/web/api/match). 

I declare that anything following the `/quizzes/` portion of the Route will be an `:id`. I pass props into the callback and spread the props object into the Quiz component as outlined by the React Router documentation. All this to gain access to the piece of the URL I need. Now when the user is at `myapp.com/quizzes/1` a Quiz component will be rendered. Once this component mounts it will use the 1 from the URL as an ID  and make a call to my backend to filter through my Quiz database. If the URL were `myapp.com/quizzes/cat` then my API call would try using `cat` as an ID and an error would be sent back from my database. Unless of course, my database contains a quiz with the ID of `cat`.

![Cat Data being sent back](https://media.giphy.com/media/ngs9Nqu0pqkec/source.gif)

*It's worth noting when I wrote the first project I was very new to React and I had been instructed to use the render method to gain access to props. Looking back, I may have been able to make this code less tedious by using the component method of Route where the components already have access to `match, history & history` as you'll see me do in the next example.*

Here is what that same functionality looks like with the useParams() hook. 

```javascript
<Route exact path="/seasons/:id" component={Season} />

const Team = () => {
   const [state, setState] = useState({});
   const { id }= useParams();

   useEffect(() => {
      api.getTeam(id).then(data => {
         //logic 
      }
};
```

Once again I declare anything following `/seasons/` will be an `:id`. Gaining access to the `params` is as simple as calling the hook and destructuring the match object, which I know will have a key of `id`, which points to my value (ie `1` or `cat`). I don't have to chain calls like in the last example `props.match.params.id`. 

I'm still learning about all the benefits of hooks but I do prefer the look of the code. Thanks for reading, and I'm happy to share my limited knowledge if you have any questions. I'm also very interested in feedback on my use cases.

___

Update: I've been recently working in typescript. I'm revisiting this article to add how to use this hook with TS. This is assuming you have some basic understanding of Typescript. If you don't, I'd recommend this very basic guide : [Typescript for Beginner Programmers by ChibiCode](https://ts.chibicode.com/).

In order to `useParams` you need to implement a generic for useParams. Building on my example above, I need to type the `id`.

```typescript

type QuizParams = {
  id: string;
};

// In order to implement that, I'd apply my type to the hook when calling it.

const { id } = useParams<QuizParams>();
```

Now typescript knows what to expect as a return value from  the `useParams` hook.