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:
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?
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>();
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.
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.
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.
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>>()
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