@burnsred/endpoint
v1.0.1
Published
This library provides a convenient wrapper around an Axios client for making API calls using Entity classes.
Downloads
37
Readme
Endpoints
This library provides a convenient wrapper around an Axios client for making API calls using Entity classes.
Quick Start
First, create an Endpoint instance for your Entity.
import { axios } from "axios";
import { TodoEntity, type Todo } from "../todo";
export const TodoAPI = new EntityEndpoint<Todo>({
entity: TodoEntity,
baseUrl: "/todo/",
client: axios,
});
Issue requests:
// By default, it will make a GET request, and expect a list response
const todos = TodoAPI.request({}); // GET /todo/
// By passing an ID, it switches to a detail response
const todo = TodoAPI.request({ id: 6 }); // GET /todo/6
// An action can also be appended
const todos = TodoAPI.request({ action: "toggle" }); // GET /todo/toggle
const todo = TodoAPI.request({ id: 6, action: "toggle" }); // GET /todo/6/toggle
// The response parsing can be overridden
const todo = TodoAPI.request({
id: 6,
action: "toggle",
processResponse: (data) => OtherEntity.fromData(data),
});
Custom API calls
It's encouraged to encapsulate common API requests in methods on a sub-class to help DRY out the codebase.
class TodoEndpoint extends EntityEndpoint<Todo> {
toggle(id: string) {
return this.request({ action: "toggle", id });
}
}
const TodoAPI = new TodoEndpoint({ ... });
TodoAPI.toggle("6");
DRF Entity API
This is a sub-class of EntityEndpoint
with a few method added to support common CRUD operations.
For Entity<T>
you get:
list(params: QueryParams): Promise<T[]>
create(record: T): Promise<T>
get(id: string): Promise<T>
save(record: T): Promise<T>
delete(record: T): Promise<void>
useQuery
To make it easier to interact with a record from the API - especially with Forms
- there is the
useQuery
hook.
function WidgetDetail() {
const { id } = useParamms();
const query = useQuery({ api: WidgetAPI, id });
const { processing, value } = query;
if (processing) return <Loading />;
return (
<Form {...query}>
...
</Form>
);
}
useApiList
Another helper hook is useApiList
for working with lists of records.
function WidgetList() {
const { isLoading, value, errors } = useApiList({ api: WidgetAPI });
if (isLoading) return <Loading />;
return (
<>
<h1> {value.count} results found! </h1>
<ul>
{value.results.map(widget => <li>{widget.name}</li>)}
</ul>
</>
);
}
There is also a load
function returned, which can be used to reload the
results.
WARNING: Params
Note that if the params
change (not the same object) the API request will re-fire.
This may unexpectedly cause a render loop!
BAD
function UserWidgets({ userId }) {
const {} = useApiList({ api: WidgetAPI, params: { userId }})
...
}
Since the params
object is re-defined each render, this will be seen as params
changing.
This is an inherent limitation of how Object.is
works, which is used by React for Memoising.
Good
function UserWidgets({ userId }) {
const params = useMemo(() => ({ userId }), [userId]);
const {} = useApiList({ api: WidgetAPI, params });
...
}