Skip to main content

Select Hook

useReturn

The traditional method of selecting data is highly flexible and useful in any situation. But one drawback of this method is that, if your query depends on some stateful variable, you may have to manually re-fetch your data after changes are made to those variables. This can get unnecessarily complicated if you are using multiple components to make queries.

The useReturn() function is an alternate, lifecycle-friendly hook to db().return statements. It subscribes to state changes and other db executions. This is the preferred way to keep a fresh, stateful data array in your project.

This hook automatically re-fetch the data of a given query, similar to how the useEffect hook runs a function when variables in the dependency array change. .return queries are built in the same way, just don't call .all or .one.

For example, imagine a situation in which your data had an attribute called rating and your app has an <input /> that controls a state variable called minRating. The useReturn hook would keep your data [called frame] fresh as this minRating variable is changed:

const [minRating, setMinRating] = useState(0);
const { db, e, useReturn } = useEasybase();

// 1st param is a function, returning a `db().return` instance
// 2nd param is dependencies that cause a re-fetch when changed
const { frame } = useReturn(() => db().return().where(e.gt('rating', minRating)),
[minRating]);

There are two types of events that will cause a re-fetch of the data in frame:

  1. One of the stateful variables in the dependency array changed, similar to useEffect
  2. Another instance of db() did an Update, Insert, or Delete that might affect the data in frame

Let's convert the demonstration in the previous section to the React-optimized useReturn hook:

function Component() {
const [minRating, setMinRating] = useState(0);
const [limit, setLimit] = useState(10);

const { db, e, useReturn } = useEasybase();

// 1st param is a function, returning a `db().return` instance without having been executed
// 2nd param is dependencies that cause a re-fetch when changed
const { frame } = useReturn(() => db().return()
.where(e.gt('rating', minRating))
.limit(limit),
[minRating, limit]);

return (
<div>
<input
type="number"
value={minRating}
onChange={e => setMinRating(Number(e.target.value))}
/>
<input
type="number"
value={limit}
onChange={e => setLimit(Number(e.target.value))}
/>

{/*
This data re-fetches when:
1. The `limit` and `minRating` change
2. Somewhere within `EasybaseProvider`, db() is used
to Update, Delete, or Insert data to the same table
*/}
{frame.map(ele => <Card {...ele} />)}
</div>
)
}

Event Listener

The dbEventListener function takes a callback function that will be run twice whenever a db operation is executed with .all or .one.

This callback function takes 3 optional parameters:

  1. status: pending, success, error
  2. queryType: select, update, insert, delete
  3. queryCount: one, all

It will first run when the package is waiting for a response, then when the execution is finished. It also returns a function that, when run, unsubscribes that specific callback from future events.

import { useEasybase } from 'easybase-react';

function MyComponent() {
const { db, e, dbEventListener } = useEasybase();

async function eventListenerTest() {
const listenerA = dbEventListener((status, queryType, queryCount) => {
console.log("A: ", status, queryType, queryCount)
});

await db('APPS').insert({ "app name": 'MyApplify', _position: 0 }).one();

dbEventListener((status, queryType, queryCount) => {
console.log("B: ", status, queryType, queryCount)
});

listenerA();
await db('APPS').return().where(e.like('App Name', '%2')).all();

// A: pending insert one
// A: success insert one
// B: pending select all
// B: success select all
}

return (
{/* ... */}
);
}
tip

The useReturn hook utilizes dbEventListener under the hood, so take a look at that implementation as a reference.