using React-Router V6 and I tried to strongly type the dataloader functions that are using params
and also the useLoaderData
hook.
So far I have to do the following that is ugly :
A- For useLoaderData
, need to force the returnType :
const profil = useLoaderData() as TProfil;
I guess it would be cleaner to create a generic hook like export declare function useLoaderData<T>(): T;
instead of export declare function useLoaderData(): unknown;
B- for the dataloader, what is the type of the params received ? Had to force to any
, but this is uggly. How to strongly type this and declare somewhere that params is made of "id" which comes from the parameter name in the Route definition ?
const careerDetailDataLoader = async ({ params }: any): Promise<TProfil> => {
const { id } = params;
const res = await fetch(`http://localhost:4000/careers/${id}`);
const data: TProfil = await res.json();
return data;
};
<Route path=":id" element={<CareerDetailsPage />} loader={careerDetailDataLoader} />
I guess it would be cleaner to create a generic hook like export declare function useLoaderData(): T; instead of export declare function useLoaderData(): unknown;
Any solution using generics only hides a necessary type cast using as
so the generic version gives a false sense of type safety.
Remix has exactly the generic useLoaderData<T>()
that you suggest.
At the remix github repo, there is a detailed explanation of why they deprecated the generic version of the function and why the useLoaderData()
function which they ported to react-router v6 does not use generics.
(The suggested helper function in the other answer has the same problem as the deprecated function in remix.)
for the dataloader, what is the type of the params received ?
In react-router
, there is ActionFunctionArgs
which leads to Params
being defined (in @remix-run/router/dist/utils.d.ts/Params
) like this:
export type Params<Key extends string = string> = {
readonly [key in Key]: string | undefined;
};
However, you might want to check out https://stackoverflow.com/a/76579584/5882233 for a similar question (and potentially a cleaner solution) about the argument types of the loader
and action
functions of react-router
v6.