Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

required url param on React router v5 with typescript, can be undefined

I am using react-router v5.1 with TypeScript and have this route configurations:

<Router basename="/" hashType="slash">     <Switch>         <Route path="/token/:tokenName">             <TokenPage />         </Route>     </Switch> </Router>  

and I try to access the url param (tokenName) in the component, with useParams hook like so:

const TokenPage: FC<TokenPageProps> = props => {     const { tokenName } = useParams()     ... }  

However, typescript thinks that tokenName param can be undefined:

wrong tokenName typing

which does not make sense since react router won't match this route if the param is missing in the URL.

How can I fix the typing in that situation?

like image 629
Or Bachar Avatar asked Nov 28 '19 09:11

Or Bachar


People also ask

How do you use useParams in React typescript?

In order to useParams you need to implement a generic for useParams. Building on my example above, I need to type the id . type QuizParams = { id: string; }; // In order to implement that, I'd apply my type to the hook when calling it. const { id } = useParams<QuizParams>();

How do I use React router without changing URL?

To use React Router without changing the URL, we can use the MemoryRouter component. to import the MemoryRouter component and then wrap it around App to let us navigate with React Router without changing URLs.

How do I add links to my React router?

To add the link in the menu, use the <NavLink /> component by react-router-dom . The NavLink component provides a declarative way to navigate around the application. It is similar to the Link component, except it can apply an active style to the link if it is active.

How do I find the URL of a React router?

Since React is based on regular JavaScript, you can access the location property on the window interface. To get the full path of the current URL, you can use window. location. href , and to get the path without the root domain, access window.


1 Answers

In this situation, your TokenPage code is unaware it is being wrapped by a Route. You are right that if the URL does not contain the proper parameters, your component wouldn't be rendered. But Typescript isn't aware of this.

The default typing you got there is proper and you should null check the value before using it.

If ever you would want to override the typing, useParams is generic and accepts a type specifying the return value type.

interface ParamTypes {   tokenName: string } const { tokenName } = useParams<ParamTypes>() 

EDIT 09/29/20

The latest typing for useParams changed.

export function useParams<Params extends { [K in keyof Params]?: string } = {}>(): Params; 

As you can see, the new default is {} which will not imply any of the keys contained, but the generic constraints does assume that the values are of type string.

So the following line would now yield a Property 'tokenName' does not exist on type '{}'. TypeScript error.

const { tokenName } = useParams() 

To fix this, either you type the useParams with known parameters like in the first example, or you type it like this:

const { tokenName } = useParams<Record<string, string | undefined>>() 
like image 52
Joel Bourbonnais Avatar answered Sep 22 '22 15:09

Joel Bourbonnais