A solution for Remix that allows you to send binary data from loader function to React client app

superjson-remix

A solution for Remix that allows you to send binary data from your loader function to your React client app. It uses the awesome superjson package to serialize/deserialize your data automatically.

Problem

With the existing Remix approach, only JSON parsable data can be sent to the client. This is a problem for binary data such as Date, Map, Set or BigInt.

Say you have a loader function and would like to send this to the client:

import { json } from 'remix';

const loader: LoaderFunction = () => {
  const obj = {
    set: new Set([1, 2, 3]),
    now: new Date(),
    largeNumber: BigInt(9007199254740991),
  };

  return json(obj);
};

Well you’re out of luck! On the client, Set will parse to an empty object.

set: {},

Date will parse as an ISO-8601 string — not the end of the world, but certainly inconvenient.

now: '2022-03-13T16:47:37.521Z'

And you just can’t send BigInt to the client, period.

TypeError: Do not know how to serialize a BigInt

Solution

With superjson-remix, you can easily send our example data to the client. Just replace the json helper function that you normally would import from remix with an import from superjson.

- import { json } from 'remix';
+ import { json } from 'superjson-remix';

What about the client?

We do the same thing on the client. We import useLoaderData from superjson-remix instead of from remix, just like we did with json on the server.

- import { useLoaderData } from 'remix';
+ import { useLoaderData } from 'superjson-remix';

Complete example

Here is an example route that uses superjson-remix to send our data to the client.

import { json, useLoaderData } from 'superjson-remix';

export const loader = () => {
  const obj = {
    set: new Set([1, 2, 3]),
    now: new Date(),
    largeNumber: BigInt(9007199254740991),
  };

  return json(obj);
};

const MyComponent = () => {
  const { set, now, largeNumber } = useLoaderData();

  return (
    <div>
      <p>Our set: {Array.from(set).join(', ');}</p>
      <p>Server time: {now.toLocaleString()}</p>
      <p>A large number: {largeNumber.toString()}</p>
    </div>
  );
};

export default MyComponent;

It renders the following.

Our set: 1, 2, 3

Server time: 3/13/2022, 1:05:20 PM

A large number: 9007199254740991

Oh, yeah. The meta function.

We provide a withSuperJSON higher-order function that wraps your meta function and will automatically deserialize the data argument.

import { withSuperJSON } from 'superjson-remix';

export const meta = withSuperJSON(({ data }) => {
  return {
    title: 'Sample App',
    description: `Created on ${data.now.toLocaleString()}`,
  };
});

Getting Started

Install the library with your package manager of choice, e.g.:


npm i superjson-remix

or


yarn add superjson-remix

License

© 2022 Donavon West. Released under MIT license.

GitHub

View Github