Trigger API
You will learn
In the previous chapters, we learned how to fetch data from the server and how to display it. Now let us talk about how to keep the data fresh.
.$stale
property of the Query
Every Query has a .$stale
property. It is a Store that contains a boolean value. It is true
when the data in the Query is stale, and false
when it is fresh.
By default, it is true
because the Query is not fetched yet.
Data becomes stale when the Query in many cases:
- if it is updated after Mutation execution
- if it is dependent on another Query and the parent Query data is updated
- if its value is extracted from cache and the cache is not marked as fresh
In all these cases, the .$stale
property of the Query becomes true
and the Query immediately starts the process of refreshing the data.
Refresh the data manually
Sometimes you want to start a [Query] only if the data is stale and skip it if the data is fresh. For example, you got the data from the server and do not want to fetch it again until on client. For this case, you can use the .refresh
Event of the Query.
import { sample } from 'effector';
import { createJsonQuery } from '@farfetched/core';
const someQuery = createJsonQuery({
/* ... */
});
sample({ clock: appStarted, target: someQuery.refresh });
In this example, the someQuery
will be started only every time when the appStarted
event is triggered and the data in the someQuery
is stale. You can safely call the appStarted
on the server, transfer the data to the client, and call the appStarted
on the client. The someQuery
will be started only on the server and will be skipped on the client.
Refresh the data automatically
In the most cases, you want to refresh the data automatically during the lifetime of the app. For this case, you can use the keepFresh
-operator.
The following example shows how to refresh the someQuery
every time when $language
store is changed, but only after the appStarted
event is triggered.
import { keepFresh, createJsonQuery } from '@farfetched/core';
const $language = createStore('en');
const someQuery = createJsonQuery({
request: {
url: { source: $language, fn: (_, language) => `/api/${language}` },
},
});
keepFresh(someQuery, {
automatically: true,
});
sample({ clock: appStarted, target: someQuery.refresh });
If you do want to refresh the data immediately after some external trigger, you can use triggers
field of the keepFresh
-operator's config to specify the triggers.
import { keepFresh, createJsonQuery } from '@farfetched/core';
const $language = createStore('en');
const someQuery = createJsonQuery(/* ... */);
keepFresh(someQuery, { triggers: [userLoggedIn] });
sample({ clock: appStarted, target: someQuery.refresh });
External triggers
Trigger API is based on @@trigger
-protocol, so any library that implements this protocol can be used as a trigger.
Web APIs
It could be really useful to refresh the data on some application wide triggers like tab visibility or network reconnection. This kind of triggers is out of scope of Farfetched, so they are distributed as separated package — @withease/web-api
.
pnpm install @withease/web-api
yarn add @withease/web-api
npm install @withease/web-api
It is compatible with Farfetched and can be used without any additional configuration.
import { trackPageVisibility, trackNetworkStatus } from '@withease/web-api';
import { keepFresh } from '@farfetched/core';
keepFresh(someQuery, {
triggers: [trackPageVisibility, trackNetworkStatus],
});
Check documentation of @withease/web-api
for the complete list of available triggers.
Interval
If you want to refresh the data every N seconds, you can use the interval
method from patronum which is library with numerous utilities for Effector.
pnpm install patronum
yarn add patronum
npm install patronum
It is compatible with Farfetched and can be used without any additional configuration.
import { keepFresh } from '@farfetched/core';
import { interval } from 'patronum';
keepFresh(someQuery, {
// 👇 someQuery will be refreshed every 5 seconds
triggers: [interval({ timeout: 5000 })],
});
Check documentation of patronum/interval
for the complete documentation.
Mix automatic and manual refresh
You can mix automatic and manual refresh:
keepFresh(someQuery, {
automatically: true,
triggers: [userLoggedIn],
});
API reference
You can find the full API reference for the keepFresh
operator in the API reference.