Probably shouldn't use generics for useLoaderData/useActionData
See original GitHub issueWe’ve kinda encouraged something I think is probably not the best thing to be doing:
interface User {
id: string;
profile: {
name: string;
}
}
export let loader: LoaderFunction = () => {
return { id: 123, email: "lol@haha.com" }
}
export default function Comp() {
let user = useLoaderData<User>();
// error!
return <div>{user.profile.name}</div>;
}
Just because you passed useLoaderData a generic doesn’t mean you will actually get a user.
The safest thing to do here is use a type guard so that the type system and the runtime do the right thing.
function isUser(user: any): user is User {
// of course you can be as thorough as you want here
return user.id && user.profile && user.profile.name;
}
export default function Comp() {
let user = useLoaderData();
if (!isUser(user)) {
return <div>We got an unexpected thing from the server ...</div>
}
// TS now knows this is a real user, without the `useLoaderData` generic.
return <div>{user.profile.name}</div>;
}
Do we want to keep this convenience with the current type-system-is-lying-to-you tradeoff?
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:5 (5 by maintainers)
Top Results From Across the Web
remix/0003-infer-types-for-useloaderdata-and-useactiondata ...
In Remix v1.6.4, types for both useLoaderData and useActionData are parameterized with a generic: type MyLoaderData = { /* .
Read more >Dominik on Twitter: ".@ryanflorence will `useLoaderData` get ...
will `useLoaderData` get a generic that you can pass, ... I'm thinking: const data = useLoaderData<Awaited<ReturnType<typeof loader>>().
Read more >Create Infinite Scroll Images in Remix - Media Jams
This tutorial will walk us through implementing infinite scroll in an image gallery using the react-infinite-scroll-component with Remix.
Read more >First thoughts on Remix
My first impression is that it shouldn't be necessary? Why can't I go export const loader = someRemixUtility(async () => {}) instead, removing ......
Read more >Remix - Full Context Review
useLoaderData. ,. useActionData. and. useFetcher. hooks. In this area, Remix goes farther than any similar framework and handles the data ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I would prefer the generic here, is my way to tell TS that function returns something I know, and if for some reason the server returns anything else that should throw a 500 status and render my error boundary component anyway
I think we definitely want a generic here. As cool as typescript is, it isn’t bullet proof. Generics are a convenient way for you to tell TS you know what you’re doing.
On Thu, Aug 5, 2021 at 1:41 PM Ryan Florence @.***> wrote:
– – Michael