Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanflorence/7de8c27474b299c6c2f357f785cfde77 to your computer and use it in GitHub Desktop.
Save ryanflorence/7de8c27474b299c6c2f357f785cfde77 to your computer and use it in GitHub Desktop.
// src/entry-browser.js
import React from "react";
import { unstable_createRoot as createRoot } from "react-dom";
import Remix from "@remix-run/react/browser";
import App from "./components/App";
// default cache, every location gets its own data, even at the same pathname
function createLocationCache() {
return {
write({ cache, data, routeModule, location, params, routeId }) {
cache[location.key] = cache[location.key] || {};
cache[location.key][routeId] = data;
return cache;
},
read({ cache, params, routeModule, location, routeId }) {
return cache[location.key][routeId];
},
};
}
// different locations but same pathname share the cache
function createPathnameCache() {
return {
write({ cache, data, routeModule, location, params, routeId }) {
cache[location.pathname] = cache[location.pathname] || {};
cache[location.pathname][routeId] = data;
return cache;
},
read({ cache, params, routeModule, location, routeId }) {
return cache[location.pathname][routeId];
},
};
}
// delegate to the route modules themselves, each has the ability to change the
// entire cache, making it possible to normalize on writes so that data is
// completely independant of locations
function createRouteModuleDelegateCache() {
// can facilitate a normalized cache with normalizr, each route module can use
// the parts of the schema it needs so that the enitre schema isn't needed in
// the initial bundle
return {
write({ cache, data, routeModule }) {
return routeModule.writeData(cache, data);
},
read({ cache, params, routeModule }) {
return routeModule.readData(cache, params);
},
};
}
// In a component, the setter for useRouteData will end up calling `cache.write`
function SomePage() {
let [routeData, setRouteData] = useRouteData();
let someClickHandler = () => {
// will go to cache.write so should be shaped like the result of the route loader
let newData = {}
setRouteData(newData)
}
}
createRoot(document, { hydrate: true }).render(
// pass it in to remix, only need this in the browser because we can use
// the cache.write when we hydrate from the client handoff
<Remix cache={cache}>
<App />
</Remix>
);
///////////////////////////////////
// src/routes/Article.js
import React from "react";
import { normalize, denormalize } from "normalizr";
import { useRouteData } from "@remix-run/react";
import { article } from "../schema";
export function writeData(cache, data) {
let normalized = normalize(data, article);
return Object.assign({}, cache, normalized.entities);
}
export function readData(cache, params) {
return denormalize(params.articleId, article, cache);
}
export default function Article() {
let data = useRouteData();
return <ArticlePage data={data} />;
}
// Data from the loader looks like this:
// {
// "id": "123",
// "author": {
// "id": "1",
// "name": "Paul"
// },
// "title": "My awesome blog post",
// "comments": [
// {
// "id": "324",
// "commenter": {
// "id": "2",
// "name": "Nicole"
// }
// }
// ]
// }
// normalizer normalizes it to this and they store `entities` as the cache
// {
// result: "123",
// entities: {
// "articles": {
// "123": {
// id: "123",
// author: "1",
// title: "My awesome blog post",
// comments: [ "324" ]
// }
// },
// "users": {
// "1": { "id": "1", "name": "Paul" },
// "2": { "id": "2", "name": "Nicole" }
// },
// "comments": {
// "324": { id: "324", "commenter": "2" }
// }
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment