There are 4 useful hooks to work with your backend:
- simple hooks which are solely based on the API:
- query hooks that wraps the API in SWR:
Setup
In order to use them, make sure you wrap your <App />
inside <ClientProvider />
, so that these hooks point to your bknd instance:
import { ClientProvider } from "bknd/client";
export default function App() {
return <ClientProvider>
{/* your app */}
</ClientProvider>
}
For all other examples below, we’ll assume that your app is wrapped inside the ClientProvider
.
useApi()
To use the simple hook that returns the Api, you can use:
import { useApi } from "bknd/client";
export default function App() {
const api = useApi();
// ...
}
useApiQuery()
This hook wraps the API class in an SWR hook for convenience. You can use any API endpoint
supported, like so:
import { useApiQuery } from "bknd/client";
export default function App() {
const { data, ...swr } = useApiQuery((api) => api.data.readMany("comments"));
if (swr.error) return <div>Error</div>
if (swr.isLoading) return <div>Loading...</div>
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
Props
-
selector: (api: Api) => FetchPromise
The first parameter is a selector function that provides an Api instance and expects an
endpoint function to be returned.
-
options
: optional object that inherits from SWRConfiguration
type Options <Data> = import("swr").SWRConfiguration & {
enabled? : boolean;
refine? : (data: Data) => Data | any;
}
enabled
: Determines whether this hook should trigger a fetch of the data or not.
refine
: Optional refinement that is called after a response from the API has been
received. Useful to omit irrelevant data from the response (see example below).
Using mutations
To query and mutate data using this hook, you can leverage the parameters returned. In the
following example we’ll also use a refine
function as well as revalidateOnFocus
(option from
SWRConfiguration
) so that our data keeps updating on window focus change.
import { useEffect, useState } from "react";
import { useApiQuery } from "bknd/client";
export default function App() {
const [text, setText] = useState("");
const { data, api, mutate, ...q } = useApiQuery(
(api) => api.data.readOne("comments", 1),
{
// filter to a subset of the response
refine: (data) => data.data,
revalidateOnFocus: true
}
);
const comment = data ? data : null;
useEffect(() => {
setText(comment?.content ?? "");
}, [comment]);
if (q.error) return <div>Error</div>
if (q.isLoading) return <div>Loading...</div>
return (
<form
onSubmit={async (e) => {
e.preventDefault();
if (!comment) return;
// this will automatically revalidate the query
await mutate(async () => {
const res = await api.data.updateOne("comments", comment.id, {
content: text
});
return res.data;
});
return false;
}}
>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
<button type="submit">Update</button>
</form>
);
}
useEntity()
This hook wraps the endpoints of DataApi
and returns CRUD options as parameters:
import { useState, useEffect } from "react";
import { useEntity } from "bknd/client";
export default function App() {
const [data, setData] = useState<any>();
const { create, read, update, _delete } = useEntity("comments", 1);
useEffect(() => {
read().then(setData);
}, []);
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
If you only supply the entity name as string without an ID, the read
method will fetch a list
of entities instead of a single entry.
Props
Following props are available when using useEntityQuery([entity], [id?])
:
entity: string
: Specify the table name of the entity
id?: number | string
: If an id given, it will fetch a single entry, otherwise a list
Returned actions
The following actions are returned from this hook:
create: (input: object)
: Create a new entry
read: (query: Partial<RepoQuery> = {})
: If an id was given,
it returns a single item, otherwise a list
update: (input: object, id?: number | string)
: If an id was given, the id parameter is
optional. Updates the given entry partially.
_delete: (id?: number | string)
: If an id was given, the id parameter is
optional. Deletes the given entry.
useEntityQuery()
This hook wraps the actions from useEntity
around SWR
. The previous example would look like
this:
import { useEntityQuery } from "bknd/client";
export default function App() {
const { data } = useEntityQuery("comments", 1);
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
Using mutations
All actions returned from useEntityQuery
are conveniently wrapped around the mutate
function,
so you don’t have think about this:
import { useState, useEffect } from "react";
import { useEntityQuery } from "bknd/client";
export default function App() {
const [text, setText] = useState("");
const { data, update, ...q } = useEntityQuery("comments", 1);
const comment = data ? data : null;
useEffect(() => {
setText(comment?.content ?? "");
}, [comment]);
if (q.error) return <div>Error</div>
if (q.isLoading) return <div>Loading...</div>
return (
<form
onSubmit={async (e) => {
e.preventDefault();
if (!comment) return;
// this will automatically revalidate the query
await update({ content: text });
return false;
}}
>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
<button type="submit">Update</button>
</form>
);
}