Skip to content

Instantly share code, notes, and snippets.

@sergiodxa
Created January 5, 2021 22:53
Show Gist options
  • Save sergiodxa/9181ba232d750bdb308f6e53e40002ae to your computer and use it in GitHub Desktop.
Save sergiodxa/9181ba232d750bdb308f6e53e40002ae to your computer and use it in GitHub Desktop.
A React Query wrapper to fetch individual entities from a REST API
import { useQuery, QueryConfig } from "react-query";
type ID = string | number;
type Resource = { name: string; id: ID };
class APIClientError extends Error {}
class APIServerError extends Error {}
export async function getEntity<Entity = unknown>(
{ name, id }: Resource,
parent: Resource,
) {
const url = new URL(
parent
? [parent.name, parent.id, name, id].join("/")
: [name, id].join("/"),
new URL("/api/v2/", window.location.toString()),
);
const res = await fetch(url.toString(), {
method: "GET",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
});
if (!res.ok) {
if (res.status >= 500) throw new APIServerError(res.statusText);
if (res.status >= 400) throw new APIClientError(res.statusText);
throw new Error(res.statusText);
}
const data = await res.json();
return data as Entity;
}
export function getEntityKey({ name, id }: Resource, parent: Resource) {
return parent
? ([parent.name, parent.id, name, id] as const)
: ([name, id] as const);
}
export function useEntity<Entity = unknown>(
resource: string,
id: ID,
parent: Resource,
options: QueryConfig<Entity, Error>,
) {
return useQuery<Entity, Error>(
getEntityKey({ name: resource, id }, parent),
() => getEntity<Entity>({ name: resource, id }, parent),
{
suspense: true,
...options,
},
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment