Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 10, 2023. It is now read-only.
/react-loadsPublic archive

React Loads is a backend agnostic library to help with external data fetching & caching in your UI components.

License

NotificationsYou must be signed in to change notification settings

jxom/react-loads

Repository files navigation

React Loads is a backend agnostic library to help with external data fetching & caching in your UI components.

Features

  • Hooks andRender Props to manage your async states & response data
  • Backend agnostic. Use React Loads with REST, GraphQL, or Web SDKs
  • Renderer agnostic. Use React Loads with React DOM, React Native, React VR, etc
  • Automated caching & revalidation to maximise user experience between page transitions
  • React Suspense support
  • SSR support
  • Preloading support
  • Polling support to load data every x seconds
  • Request deduping to minimise over-fetching of your data
  • Focus revalidation to re-fetch your data when the browser window is focused
  • Resources to allow your to hoist common async functions for built-in caching & reusability
  • Finite set of state variables to avoid cryptic ternaries and impossible states
  • External cache support
  • Optimistic responses
  • Pretty small –5kB gzipped

Table of Contents

Installation

yarn add react-loads

or npm:

npm install react-loads

Quick start

With Hooks

importReactfrom'react';import*asLoadsfrom'react-loads';asyncfunctionfetchRandomDog(){// Dog fetcher logic here!// You can use any type of backend here - REST, GraphQL, you name it!}exportdefaultfunctionRandomDog(){const{    response,    error,    isPending,    isResolved,    isRejected}=Loads.useLoads('randomDog',fetchRandomDog);return(<div>{isPending&&'Loading...'}{isResolved&&<imgsrc={response.imgSrc}/>}{isRejected&&`Oh no!${error.message}`}</div>)}

See the CodeSandbox example

TheuseLoads function accepts three arguments: acontext key, anasync function, and aconfig object (not used in this example). Thecontext key will store the response of thefetchRandomDog function in the React Loads cache against the key. Theasync function is a function that returns a promise, and is used to fetch your data.

TheuseLoads function also returns a set of values:response,error, and a finite set of states (isIdle,isPending,isResolved,isRejected, and a few others). If yourasync function resolves, it will update theresponse &isResolved values. If it rejects, it will update theerror value.

IMPORTANT NOTE: You must provide useLoads with a memoized promise (viaReact.useCallback orbounded outside of your function component as seen in the above example), otherwise useLoads will be invoked on every render.

If you are usingReact.useCallback, thereact-hooks ESLint Plugin is incredibly handy to ensure your hook dependencies are set up correctly.

With Render Props

If your codebase isn't quite hook ready yet, React Loads provides a Render Props interface which shares the same API as the hook:

importReactfrom'react';import{Loads}from'react-loads';asyncfunctionfetchRandomDog(){// Dog fetcher logic here!// You can use any type of backend here - REST, GraphQL, you name it!}classRandomDogextendsReact.Component{render(){return(<Loadscontext="randomDog"fn={fetchRandomDog}>{({ response, error, isPending, isResolved, isRejected})=>(<div>{isPending&&'Loading...'}{isResolved&&<imgsrc={response.imgSrc}/>}{isRejected&&`Oh no!${error.message}`}</div>)}</Loads>)}}

See the CodeSandbox example

More examples

Guides

Starting out

There are two main hooks:useLoads &useDeferredLoads.

  • useLoads is called on first render,
  • useDeferredLoads is called when you choose to invoke it (it's deferred until later).

Let's focus on theuseLoads hook for now, we will explainuseDeferredLoads in the next section.

TheuseLoads hook accepts 3 parameters:

  • A"context key" in the form of astring.
    • It will help us with identifying/storing data, deduping your requests & updating otheruseLoad's sharing the same context
    • Think of it as the namespace for your data
  • An"async function" in the form of afunction that returns a promise
    • This will be the function to resolve the data
  • An optional"config" in the form of anobject
importReactfrom'react';import*asLoadsfrom'react-loads';asyncfunctionfetchRandomDog(){// Dog fetcher logic here!// You can use any type of backend here - REST, GraphQL, you name it!}exportdefaultfunctionRandomDog(){const{    response,    error,    load,    isPending,    isReloading,    isResolved,    isRejected}=Loads.useLoads('randomDog',fetchRandomDog);return(<div>{isPending&&'Loading...'}{isResolved&&(<div><imgsrc={response.imgSrc}/><buttononClick={load}disabled={isReloading}>Load another</button></div>)}{isRejected&&`Oh no!${error.message}`}</div>)}

See the CodeSandbox example

TheuseLoads hook represents a finite state machine and returns a set of state variables:

  • isIdle if the async function hasn't been invoked yet (relevant foruseDeferredLoads)
  • isPending for when the async function is loading
  • isReloading for when the async function is reloading (typically truthy when data already exists in the cache)
  • isResolved for when the async function has resolved
  • isRejected for when the async function has errored

It also returns aresponse variable if your function resolves, and anerror variable if rejected.

If you want to reload your data,useLoads also returns aload variable, which you can invoke.

TheuseLoads hook returnssome other variables as well.

Deferring

Sometimes you don't want your async function to be invoked straight away. This is where theuseDeferredLoads hook can be handy. It waits until you manually invoke it.

importReactfrom'react';import*asLoadsfrom'react-loads';asyncfunctionfetchRandomDog(){// Dog fetcher logic here!// You can use any type of backend here - REST, GraphQL, you name it!}exportdefaultfunctionRandomDog(){const{    response,    error,    load,    isIdle,    isPending,    isReloading,    isResolved,    isRejected}=Loads.useDeferredLoads('randomDog',fetchRandomDog);return(<div>{isIdle&&<buttononClick={load}>Load a dog</button>}{isPending&&'Loading...'}{isResolved&&(<div><imgsrc={response.imgSrc}/><buttononClick={load}disabled={isReloading}>Load another</button></div>)}{isRejected&&`Oh no!${error.message}`}</div>)}

See the CodeSandbox example

In the above example, the dog image is fetched via theload variable returned fromuseDeferredLoads.

There are also some cases where including acontext key may not make sense. You can omit it if you want like so:

const{ ...}=useDeferredLoads(fetchRandomDog);

Configuration

You can set configuration on either a global level, or a localuseLoads level.

On a global level

By setting configuration on a global level, you are setting defaults for all instances ofuseLoads.

import*asLoadsfrom'react-loads';constconfig={dedupingInterval:1000,timeout:3000};exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>      ...<Loads.Provider>  )}

Warning: Theconfig prop must be memoized. Either memoize it usingReact.useMemo or put it outside of the function component.

See the full set of configuration options here

On auseLoads level

By setting configuration on auseLoads level, you are overriding any defaults set byLoads.Provider.

const{ ...}=useLoads('randomDog',fetchRandomDog,{dedupingInterval:1000,timeout:3000});

See the full set of configuration options here

Variables

If your async function needs some dependant variables (such as an ID or query parameters), use thevariables attribute in theuseLoads config:

asyncfunctionfetchDog(id){returnaxios.get(`https://dog.api/${id}`);}exportdefaultfunctionDogImage(props){const{ ...}=useLoads('dog',fetchDog,{variables:[props.id]});}

See the CodeSandbox example

Thevariables attribute accepts an array of values. If your async function accepts more than one argument, you can pass through just as many values tovariables as the function accepts:

asyncfunctionfetchDog(id,foo,bar){// id = props.id// foo = { hello: 'world' }// bar = truereturnaxios.get(`https://dog.api/${id}`);}exportdefaultfunctionDogImage(props){const{ ...}=useLoads('dog',fetchDog,{variables:[props.id,{hello:'world'},true]});}

WARNING!

It may be tempting to not use thevariables attribute at all, and just use the dependencies outside the scope of the function itself. While this works, it will probably produce unexpected results as the cache looks up the record against thecontext key ('dog') and the set ofvariables. However, in this case, it will only look up the record against the'dog' context key meaning that every response will be stored against that key.

// DON'T DO THIS! IT WILL CAUSE UNEXPECTED RESULTS!exportdefaultfunctionDogImage(props){constid=props.id;constfetchDog=React.useCallback(()=>{returnaxios.get(`https://dog.api/${id}`);})const{ ...}=useLoads('dog',fetchDog);}

Conditional loaders

If you want to control whenuseLoads invokes it's async function via a variable, you can use thedefer attribute in the config.

exportdefaultfunctionRandomDog(props){// Don't fetch until shouldFetch is truthy.const{ ...}=useLoads('randomDog',fetchRandomDog,{defer:!props.shouldFetch});}

See the CodeSandbox example

Dependant loaders

There may be a case where oneuseLoads depends on the data of anotheruseLoads, where you don't want subsequentuseLoads to invoke the async function until the firstuseLoads resolves.

If you pass a function tovariables and the function throws (due todog being undefined), then the async function will be deferred while it is undefined. As soon asdog is defined, then the async function will be invoked.

exportdefaultfunctionRandomDog(props){const{response:dog}=useLoads('randomDog',fetchRandomDog);const{response:friends}=useLoads('dogFriends',fetchDogFriends,{variables:()=>[dog.id]})}

See the CodeSandbox example

Caching

Caching in React Loads comes for free with no initial configuration. React Loads uses the "stale while revalidate" strategy, meaning thatuseLoads will serve you with cached (stale) data, while it loads new data (revalidates) in the background, and then show the new data (and update the cache) to the user.

Caching strategy

React Loads uses thecontext argument given touseLoads to store the data in-memory against a"cache key". Ifvariables are present, then React Loads will generate a hash and attach it to thecache key. In a nutshell,cache key = context + variables.

// The response of this will be stored against a "cache key" of `dog.1`const{ ...}=useLoads('dog',fetchDog,{variables:[1]});

React Loads will automatically revalidate whenever the cache key (context orvariables) changes.

// The fetchDog function will be fetched again if `props.context` or `props.id` changes.const{ ...}=useLoads(props.context,fetchDog,{variables:[props.id]});

You can change the caching behaviour by specifying acacheStrategy config option. By default, this is set to"context-and-variables", meaning that the cache key will be a combination of thecontext +variables.

// The response of this will be stored against a `dog` key, ignoring the variables.const{ ...}=useLoads('dog',fetchDog,{cacheStrategy:'context-only',variables:[props.id]});

Stale data & revalidation

By default, React Loads automatically revalidates data in the cache after5 minutes. That is, when theuseLoads is invoked and React Loads detects that the data is stale (hasn't been updated for 5 minutes), thenuseLoads will invoke the async function and update the cache with new data. You can change the revalidation time using therevalidateTime config option.

// Set it globally:import*asLoadsfrom'react-loads';constconfig={revalidateTime:600000}exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>      ...</Loads.Provider>)}// Or, set it locally:exportdefaultfunctionRandomDog(){const{ ...}=useLoads('randomDog',fetchRandomDog,{revalidateTime:600000});}

Cache expiry

React Loads doesn't set a cache expiration by default. If you would like to set one, you can use thecacheTime config option.

// Set it globally:import*asLoadsfrom'react-loads';constconfig={cacheTime:600000}exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>      ...</Loads.Provider>)}// Or, set it locally:exportdefaultfunctionRandomDog(){const{ ...}=useLoads('randomDog',fetchRandomDog,{cacheTime:600000});}

Slow connections

On top of theisPending &isReloading states, there are substates calledisPendingSlow &isReloadingSlow. If the request is still pending after 5 seconds, then theisPendingSlow/isReloadingSlow states will become truthy, allowing you to indicate to the user that the request is loading slow.

exportdefaultfunctionRandomDog(){const{ isPending, isPendingSlow}=useLoads('randomDog',fetchRandomDog);return(<div>{isPending&&`Loading...${isPendingSlow&&'Taking a while...'}`}</div>)}

By default, the timeout is5 seconds, you can change this with thetimeout config option.

Polling

React Loads supports request polling (reload data everyx seconds) with thepollingInterval config option.

// Calls fetchRandomDog every 3 seconds.const{ ...}=useLoads('randomDog',fetchRandomDog,{pollingInterval:3000});

You can also add apollWhile config option if you wish to control the behaviour of when the polling should run.

// Calls fetchRandomDog every 3 seconds while `shouldPoll` is truthy.constshouldPoll=shouldTheDogBePollingRightNow();const{ ...}=useLoads('randomDog',fetchRandomDog,{pollingInterval:3000,pollWhile:shouldPoll});

You can also access therecord as the first parameter ofpollWhile if you provide a function.

// Calls processImage every 3 seconds while it's status is 'processing'.const{ ...}=useLoads('randomDog',fetchRandomDog,{pollingInterval:3000,pollWhile:record=>record?.response?.status==='processing'});

Deduping

By default, all your requests are deduped on an interval of500 milliseconds. Meaning that if React Loads sees more than one request of the same cache key in under 500 milliseconds, it will not invoke the other requests. You can change the deduping interval with thededupingInterval config option.

Suspense

To use React Loads with Suspense, you can set thesuspense config option totrue.

// Set it globally:import*asLoadsfrom'react-loads';constconfig={suspense:true}exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>      ...</Loads.Provider>)}// Or, set it locally:exportdefaultfunctionRandomDog(){const{ ...}=useLoads('randomDog',fetchRandomDog,{suspense:true});}

Once enabled, you can use theReact.Suspense component to replicate theisPending state, and useerror boundaries to display error states.

functionRandomDog(){const{ response}=useLoads('randomDog',fetchRandomDog,{suspense:true});return<imgsrc={response.imgSrc}/>;}functionApp(){return(<React.Suspensefallback={<div>loading...</div>}><RandomDog/></React.Suspense>)}

Optimistic responses

React Loads has the ability to optimistically update your data while it is still waiting for a response (if you know what the response will potentially look like). Once a response is received, then the optimistically updated data will be replaced by the response.This article explains the gist of optimistic UIs pretty well.

ThesetResponse function is provided in ameta object as seen below.

importReactfrom'react';import*asLoadsfrom'react-loads';asyncfunctionfetchDog(id){// Fetch the dog}functionupdateDog(id,data){returnasyncmeta=>{meta.setResponse(data);// Fetch the dog}}exportdefaultfunctionRandomDog(props){constdogRecord=Loads.useLoads('dog',fetchDog,{variables:[props.id]});constupdateDogRecord=Loads.useDeferredLoads('dog',updateDog);return(<div>{dogRecord.isPending&&'Loading...'}{dogRecord.isResolved&&<imgsrc={dogRecord.response.imgSrc}/>}{dogRecord.isRejected&&`Oh no!${dogRecord.error.message}`}<buttononClick={()=>updateDogRecord.load(props.id,{imgSrc:'cooldog.png'})}>        Update dog</button></div>)}

Resources

For async functions which may be used & invoked in many parts of your application, it may make sense to hoist and encapsulate them into resources.A resource consists of one (or more) async function as well as a context.

Below is an example of a resource and it's usage:

importReactfrom'react';import*asLoadsfrom'react-loads';// 1. Define your async function.asyncfunctiongetUsers(){constresponse=awaitfetch('/users');constusers=awaitresponse.json();returnusers;}// 2. Create your resource, and attach the loading function.constusersResource=Loads.createResource({context:'users',fn:getUsers});functionMyComponent(){// 3. Invoke the useLoads function in your resource.constgetUsersRecord=usersResource.useLoads();// 4. Use the record variables:constusers=getUsersRecord.response||[];return(<div>{getUsersRecord.isPending&&'loading...'}{getUsersRecord.isResolved&&(<ul>{users.map(user=>(<likey={user.id}>{user.name}</li>))}</ul>)}</div>)}

See the CodeSandbox example

You can attach more than one loading function to a resource.But it's return value must be the same schema, as every response will update the cache.

You can also provide an array of 2 items to the resource creator (seen below withdelete); the first item being the async function, and the second being theconfig.

Here is an extended example using a resource with multiple async functions, split into two files (resources/users.js &index.js):

resources/users.js

import*asLoadsfrom'react-loads';asyncfunctiongetUser(id){constresponse=awaitfetch(`/users/${id}`);constuser=awaitresponse.json();returnuser;}functionupdateUser(id,data){returnasyncmeta=>{awaitfetch(`/users/${id}`,{method:'post',body:JSON.stringify(data)});// `cachedRecord` is the record that's currently stored in the cache.constcurrentUser=meta.cachedRecord.response;constupdatedUser={ ...currentUser, ...data};returnupdatedUser;}}asyncfunctiondeleteUser(id){awaitfetch(`/users/${id}`,{method:'delete'});return;}exportdefaultLoads.createResource({context:'user',fn:getUser,// You can supply either a async function, or an array of async function/config pairs.update:[updateUser,{timeout:3000}],delete:deleteUser});

index.js

importReactfrom'react';importDeleteUserButtonfrom'./DeleteUserButton';importUpdateUserFormfrom'./UpdateUserForm';importusersResourcefrom'./resources/users';functionMyComponent(props){const{ userId}=props;constgetUserRecord=usersResource.useLoads({variables:[userId]});constuser=getUserRecord.response||{};constupdateUserRecord=usersResource.update.useDeferredLoads({variables:[userId]});constdeleteUserRecord=usersResource.delete.useDeferredLoads({variables:[userId]});return(<div>{getUserRecord.isPending&&'loading...'}{getUserRecord.isResolved&&(<div>          Username:{user.name}<DeleteUserButtonisLoading={deleteUserRecord.isPending}onClick={deleteUserRecord.load}/><UpdateUserFormonSubmit={data=>updateUserRecord.load(userId,data)}/></div>)}</div>)}

External cache providers

If you would like the ability to persist response data upon unmounting the application (e.g. page refresh or closing window), a cache provider can also be utilised to cache response data.

Here is an example usingStore.js. You can either set the external cache provider on a global level or auseLoads level.

On a global level

import*asLoadsfrom'react-loads';importstorefrom'store';constconfig={cacheProvider:{get:key=>store.get(key),set:(key,val)=>store.set(key,val),reset:()=>store.clearAll()}}exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>      ...</Loads.Provider>)}

On auseLoads level

import*asLoadsfrom'react-loads';importstorefrom'store';constcacheProvider={get:key=>store.get(key),set:(key,val)=>store.set(key,val),reset:()=>store.clearAll()}exportdefaultfunctionRandomDog(){const{ ...}=Loads.useLoads('randomDog',fetchRandomDog,{ cacheProvider});}

Preloading (experimental)

React Loads comes with the ability to eagerly preload your data. You can do so using thepreload function.

constrandomDogLoader=Loads.preload('randomDog',fetchRandomDog);

Thepreload function shares the same arguments as theuseLoads function, however,preload is not a React Hook and shouldn't be called in your render function. Instead, use it inside event handlers, route preparation, or call it on first render.

Thepreload function will essentially fetch & cache your data in the background. It does not return any value apart from auseLoads hook. When theuseLoads hook is invoked, it will read the data from the cache that was previously loaded bypreload, and won't re-fetch your data. If no cached data exists, it will go ahead and fetch it.

constrandomDogLoader=Loads.preload('randomDog',fetchRandomDog);functionRandomDog(){const{ response}=randomDogLoader.useLoads({suspense:true});return<imgsrc={response.imgSrc}/>;}functionApp(){return(<React.Suspensefallback={<div>Loading...</div>}><RandomDog/></React.Suspense>)}

See the CodeSandbox example

Render-as-you-fetch

Thepreload function is designed to implement the"render-as-you-fetch" pattern. Ideally,preload can be invoked when preparing your routes, or inside an event handler, where you can then use theuseLoads function inside your component.

Basic example

Event handler example

Routing example

API

useLoads

const{  response,  error,  load,  isIdle,  isPending,  isPendingSlow,  isReloading,  isReloadingSlow,  isResolved,  isRejected,  reset,  state,  isCached}=useLoads(context,fn,config);

Parameters

context

string

A unique identifier for the request.

fn

function

A function that returns a promise to retrieve your data.

config

object | optional

A set ofconfiguration options

Returns

response

any

Response from the resolved promise (fn).

error

any

Error from the rejected promise (fn).

load

function

Trigger to invokefn.

isIdle

boolean

Returnstrue if the state is idle (fn has not been invoked).

isPending

boolean

Returnstrue if the state is pending (fn is in a pending state).

isPendingSlow

boolean

Returnstrue if the state is pending for longer thantimeout milliseconds.

isReloading

boolean

Returnstrue if the state is reloading (fn is in a pending state &fn has already been invoked or cached).

isReloadingSlow

boolean

Returnstrue if the state is reloading for longer thantimeout milliseconds.

isResolved

boolean

Returnstrue if the state is resolved (fn has been resolved).

isRejected

boolean

Returnstrue if the state is rejected (fn has been rejected).

reset

function

Function to reset the state & response back to an idle state.

state

string

State of the promise (fn).

isCached

boolean

Returnstrue if data exists in the cache.

useDeferredLoads

const{  response,  error,  load,  isIdle,  isPending,  isPendingSlow,  isReloading,  isReloadingSlow,  isResolved,  isRejected,  reset,  state,  isCached,  update}=useDeferredLoads(context,fn,config);// OR}=useDeferredLoads(fn,config);

Parameters

context

string | optional

A unique identifier for the request. This is optional foruseDeferredLoads.

fn

function

A function that returns a promise to retrieve your data.

config

object | optional

A set ofconfiguration options

Returns

Same asuseLoads

useCache

A hook which enables you to retrieve a record from the cache.

// Including `context` onlyconstrandomDogRecord=useCache('randomDog');// Including `context` & `variables`constdogRecord=useCache('dog',{variables:[0]});

Parameters

context

The unique identifier of the record to retrieve.

variables

An array of variables (parameters).

Returns

response

any

Response of the cached record.

error

any

Error of the cached record.

state

any

State of the cached record.

useGetStates

A hook which composes a set of records, and gives you a singular state.

Without usinguseGetStates, you may run into situations like this:

constrandomDogRecord=useLoads('randomDog',fetchRandomDog);constdogFriendsRecord=useLoads('dogFriends',fetchDogFriends);<div>{(randomDogRecord.isPending||dogFriendsRecord.isPending)&&'Loading...'}{randomDogRecord.isResolved&&dogFriendsRecord.isResolved&&'Loaded!'}</div>

But, if you compose your records insideuseGetStates, you can clean up your state variables:

constrandomDogRecord=useLoads('randomDog',fetchRandomDog);constdogFriendsLoader=useLoads('dogFriends',fetchDogFriends);const{ isPending, isResolved, isRejected}=useGetStates(randomDogRecord,dogFriendsRecord);

<Provider>

Set global configuration with the<Provider> component.

import*asLoadsfrom'react-loads';constconfig={cacheTime:600000}exportdefaultfunctionApp(){return(<Loads.Providerconfig={config}>{/* ... */}</Loads.Provider>)}

Props

config

Object

An object ofconfiguration options

createResource

constresource=createResource(options);

Parameters

options.context

string

The context of the resource. Used to generate a cache key.

options.fn

function

A function that returns a promise to retrieve your data.

Any key can be an async function!

Any key you provide to the resource is an async function.

constdogsResource=createResource({context:'dogs',fn:getDogs,create:createDog,foo:getDogFoo,bar:getDogBar,baz:getDogBaz});// In your function component - will invoke the `bar` async function in createResource:dogsResource.bar.useLoads();

Returns

useLoads

AuseLoads hook which can be invoked in your function component.

The arguments are a bit different to the standaloneuseLoads hook - it only optionally accepts aconfig object, and not acontext or an async function (fn).

resource.useLoads(config)
useDeferredLoads

AuseLoads hook which can be invoked in your function component.

The arguments are a bit different to the standaloneuseDeferredLoads hook - it only optionally accepts aconfig object, and not acontext or an async function (fn).

resource.useDeferredLoads(config)
preload (experimental)

Same as thepreload function, however only accepts aconfig object as it's only parameter.

resource.preload(config)

See the CodeSandbox example

preload (experimental)

constloader=preload(context,fn,config);

Parameters

context

string | optional

A unique identifier for the request. This is optional foruseDeferredLoads.

fn

function

A function that returns a promise to retrieve your data.

config

object | optional

A set ofconfiguration options

Returns

useLoads

AuseLoads hook which can be invoked in your function component.

The arguments are a bit different to the standaloneuseLoads hook - it only optionally accepts aconfig object, and not acontext or an async function (fn).

loader.useLoads(config)

Config

config={  cacheProvider,  cacheStrategy,  cacheTime,  context,  dedupingInterval,  delay,  defer,  initialResponse,  loadPolicy,  onReject,  onResolve,  pollingInterval,  pollWhenHidden,  rejectRetryInterval,  revalidateTime,  revalidateOnWindowFocus,  suspense,  throwError,  timeout,  update,  variables}

cacheProvider

{ get: function(key), set: function(key, val), reset: function() }

Set a custom cache provider (e.g. local storage, session storate, etc). Seeexternal cache providers for an example.

cacheStrategy

string | Default:"context-and-variables"

The caching strategy for your loader to determine the cache key.

Available values:

  • "context-only"
    • Caches your data against thecontext key only.
  • "context-and-variables"
    • Caches your data against a combination of thecontext key &variables.

cacheTime

number | Default:0

Time (in milliseconds) that the data remains in the cache. After this time, the cached data will be removed.

dedupingInterval

number | Default:500

Interval (in milliseconds) that requests will be deduped in this time span.

delay

number | Default:0

Time (in milliseconds) before the component transitions to the"pending" state upon invokingfn.

defer

boolean

If set totrue, the async function (fn) won't be called automatically and will be deferred until later.

Ifdefer is set to true, the initial state will beidle.

initialResponse

any

Set initial data for the request. Useful for SSR.

loadPolicy

string | Default:"cache-and-load"

A load policy allows you to specify whether or not you want your data to be resolved from the Loads cache and how it should load the data.

  • "cache-only":useLoads will only return data from the cache. It will not invoke the async function.

  • "cache-first": If a value for the loader already exists in the Loads cache, thenuseLoads will return the value that is in the cache, otherwise it will invoke the async function.

  • "cache-and-load": This is the default value and means thatuseLoads will return with the cached value if found, but regardless of whether or not a value exists in the cache, it will always invoke the async function.

  • "load-only": This means thatuseLoads will not return the cached data altogether, and will only return the data resolved from the async function.

onReject

function(error)

A hook that is invoked when the async function (fn) rejects.

onResolve

function(response)

A hook that is invoked when the async function (fn) resolves.

pollingInterval

number

If set, thenuseLoads will invoke the async function (fn) everyx amount of seconds.

pollWhile

boolean | function(record)

If set, thenuseLoads will poll while the condition is truthy.

pollWhenHidden

boolean | Default:false

If truthy, thenuseLoads will continue to poll when the window is not focused.

rejectRetryInterval

number | function(count)

If set, anduseLoads rejects, thenuseLoads will continue to try and resolvefn everyx seconds. If a function is given, you can determine the interval time with that.

Example:

// Retry every 1000 milliseconds.rejectRetryInterval:1000// Retry every "error count" * "2000 milliseconds".rejectRetryInterval:count=>count*2000

revalidateTime

number | Default:300000 (5 minutes)

Time that the data in the cache remains "fresh". After this time, data in the cache will be marked as "stale", meaning that the data will have to be reloaded on next invocation.

revalidateOnWindowFocus

boolean | Default:false

If truthy,useLoads will load the async function (fn), when the browser window is focused again.

suspense

boolean | Default:false

If truthy, this will enable React Suspense mode.

throwError

boolean | Default:false

If truthy and the async function (fn) rejects, thenuseLoads orload will throw the error.

timeout

number | Default:5000 (5 seconds)

Number of milliseconds before the component transitions to theisPendingSlow orisReloadingSlow state. Set to0 to disable.

Note:useLoads will still continue to try and resolve while in theisPendingSlow state

variables

Array<any>

An array of variables (parameters) to pass to your async function (fn).

Happy customers

  • "I'm super excited about this package" -Michele Bertoli
  • "Love the API! And that nested ternary-boolean example is a perfect example of how messy React code commonly gets without structuring a state machine." -David K. Piano
  • "Using case statements with React components is comparable to getting punched directly in your eyeball by a giraffe. This is a huge step up." -Will Hackett
  • "I used to get the shakes coding data fetch routines with React. Not anymore. Using react loads, I now achieve data fetching zen." -Claudia Nadalin
  • "After seeinghttps://twitter.com/dan_abramov/status/1039584557702553601?lang=en, we knew we had to change our loading lifecycles; React Loads was our saviour." -Zhe Wang

Acknowledgments

License

MIT ©jxom

About

React Loads is a backend agnostic library to help with external data fetching & caching in your UI components.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors4

  •  
  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp