https://github.com/dimfeld/swr-xstate
An implementation of SWR using XState
https://github.com/dimfeld/swr-xstate
Last synced: over 1 year ago
JSON representation
An implementation of SWR using XState
- Host: GitHub
- URL: https://github.com/dimfeld/swr-xstate
- Owner: dimfeld
- License: mit
- Created: 2020-07-09T08:14:22.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T12:02:36.000Z (over 3 years ago)
- Last Synced: 2024-10-07T07:06:58.481Z (almost 2 years ago)
- Language: TypeScript
- Homepage: https://swr-xstate.imfeld.dev
- Size: 1.31 MB
- Stars: 31
- Watchers: 2
- Forks: 1
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
This is an implementation of a stale-while-revalidate data fetcher implemented with the [XState](https://xstate.js.org) library. It implements many of the features found in other popular SWR libraries, such as periodic updates and disabling the fetcher when the browser is not focused.
I wrote about the design and implementation on [my website](https://imfeld.dev/writing/swr_with_xstate), and there's also a simple [example site](https://swr-xstate.imfeld.dev).
```typescript
/** The fetcher function can return this if it tried to fetch and found the data was unchanged. */
export const UNMODIFIED = Symbol('unmodified');
export interface FetchResult {
data?: T;
error?: Error;
/** When this data was fetched */
timestamp: number;
/** True if this is the stale data. Absent otherwise. */
stale? : boolean;
}
export interface DebugMessage {
id: string;
state: State;
event: AnyEventObject;
}
export interface InitialData {
data: T;
timestamp?: number;
}
export interface AutoFetcherOptions<
T
> {
/** A string that can uniquely identify the resource to be fetched. This is
* passed as an argument to the `fetch` and `initialData` functions.
*/
key: string;
/** A name for this fetcher. Will default to the vaue of `key` if not set. */
name?: string;
/** A function that should fetch the "stale" data. Called when the fetcher is created. */
initialData?: (key:string) => Promise|null>;
/** `fetcher` is called periodically to retrieve new data */
fetcher: (key: string) => Promise,
/** `receive` is called when new data has arrived. */
receive: (result : FetchResult) => any;
/** Number of milliseconds between refresh attempts, unless refresh is forced. */
autoRefreshPeriod?: number;
/** Maximum number of milliseconds to wait between refresh attempts in case of error. Defaults to 1 minute. */
maxBackoff? : number;
/** True if the state machine should permit refreshes by default. False if it should wait for `setPerrmitted(true)`. Defaults to true. */
initialPermitted? : boolean;
/** True if the state machine should be enabled by default. False if it should wait for `setEnabled(true)`
* with `true` as the data before it starts refreshing. Defaults to true.
* Typically this is used to disable updates if nothing in the application is actually listening for changes.
*/
initialEnabled? : boolean;
/** Given an object, this function should print out debug information. This can be `console.log` if you want, or something like the `debug` module. Called on every state transition. */
debug?: (msg : DebugMessage) => any;
}
export interface AutoFetcher {
/** Set if fetching is enabled. It might be disabled if you know that nothing is using this data right now. */
setEnabled: (enabled : boolean) => void;
/** Set if fetching is permitted. Fetching might not be permitted if the user is not logged in or lacks
* proper permissions for this endpoint, for example. */
setPermitted: (permitted: boolean) => void;
/** Force a refresh. This will not do anything if fetching has been disabled via `setPermitted`. */
refresh: () => void;
destroy: () => void;
}
/** This function creates a fetcher */
export function fetcher(options : AutoFetcherOptions) : AutoFetcher;
```