18

Why react router v6 useParams returns object with properties possibly 'undefined'?

In my code below, my IDE indicates const slug: string | undefined.

const { slug } = useParams<"slug">();

It is because of the Params type definition:

/**
 * The parameters that were parsed from the URL path.
 */
export type Params<Key extends string = string> = {
  readonly [key in Key]: string | undefined;
};

But why is not Params defined like this (without the | undefined):

export type Params<Key extends string = string> = {
  readonly [key in Key]: string;
};

If a route with a parameter matches the URL then the parameter cannot be undefined. So, is there any case when useParams returns with an undefined param?

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
soliz
  • 735
  • 1
  • 7
  • 17

3 Answers3

31

I believe this is a questionable design choice. React Router 6 doesn't support optional parameters, so there is no apparent reason, but even if it did support, it should be responsibility of the user to determine which parameters are optional.

One way to go around it is:

export type MyParams = {
  a: string;
  b: string;
  c: string;
};

const { a, b, c } = useParams<keyof MyParams>() as MyParams;
Andre Pena
  • 56,650
  • 48
  • 196
  • 243
11

Route params can be possibly undefined if the path has no defined parameters.

Example: "/path/to/page"

There are no route match params to access.

If you were to attempt to access a param

const { id } = useParams();

then id is of course, undefined.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
4

One workaround is to extend module and change the desired type.

Create src/react-router-dom.d.ts file with content:

import 'react-router-dom';

declare module 'react-router-dom' {
  export declare function useParams<
    ParamsOrKey extends string | Record<string, string | undefined> = string,
  >(): { [key in ParamsOrKey]: string };
}