Without remix-superloader, when you use loaded data with remix's useLoaderData
hook, Date objects (and others) will be strings rather than Date objects due to JSON serialization. You must be sure to parse those back into dates. remix-superloader handles parsing/serializing Dates (and Maps, Sets, BigInts, RegExps) so you don't have to think about that. remix-superloader also handles inferring types, so the useSuperLoaderData
hook is automatically properly typed.
npm i remix-superloader
import { useSuperLoaderData, encodeSuper } from 'remix-superloader';
export const loader = async ({ params }: { params: { slug?: string } }) =>
encodeSuper({
post: {
title: 'My first Post',
date: new Date(),
slug: params.slug,
},
});
export default function Post() {
const { post } = useSuperLoaderData<typeof loader>();
// without superloader, post.date is a string
// with superloader, post.date is a Date
return (
<div>
<h2>{post.title}</h2>
<p>{post.date.toLocaleDateString()}</p>
</div>
);
}
remix-superloader will convert these types that are not able to be represented in standard json for you.
- ✅ Date
- ✅ RegExp
- ✅ Map
- ✅ Set
- ✅ BigInt
- 🚫 Error
- 🚫 undefined
You can also pass headers (and other ResponseInit data) from your loader
import { encodeSuper, useSuperLoaderData } from 'remix-superloader';
const loader = async () =>
encodeSuper(
{
date: new Date(),
},
{
headers: {
'Server-Timing': serverTiming,
},
}
);
export default function Post() {
const { date } = useSuperLoaderData<typeof loader>();
return (
<div>
<h2>Hello, {date.toLocaleString()}</h2>
</div>
);
}
remix-superloader provides a generic alternative to remix's LoaderFunction
import {
encodeSuper,
useSuperLoaderData,
SuperLoaderFunction,
} from 'remix-superloader';
const loader: SuperLoaderFunction<{ date: Date }> = async () =>
encodeSuper(
{
date: new Date(),
},
{
headers: {
'Server-Timing': serverTiming,
},
}
);
export default function Post() {
const { date } = useSuperLoaderData<typeof loader>();
return (
<div>
<h2>Hello, {date.toLocaleString()}</h2>
</div>
);
}
You can customize the type converters by including a list of type (de)serializers.
import {
encodeSuper,
mapType,
defaultMappedTypes,
useSuperLoaderData,
} from 'remix-superloader';
class Greeter {
constructor(public name: string) {}
greet() {
return `Hello, ${this.name}`;
}
}
const customMappedTypes = [
...defaultMappedTypes,
mapType(
Greeter,
(greeter) => greeter.name,
(name) => new Greeter(name)
),
];
const loader = async () =>
encodeSuper(
{
greeter: new Greeter('Joe'),
},
customMappedTypes
);
export default function Post() {
const { greeter } = useSuperLoaderData<typeof loader>(customMappedTypes);
return (
<div>
<h2>{greeter.greet()}</h2>
</div>
);
}