@data-client/react
Version:
Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch
67 lines (61 loc) • 9.98 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { ExpiryStatus } from '@data-client/core';
import { useEffect, useMemo } from 'react';
import useCacheState from './useCacheState.js';
import useController from '../hooks/useController.js';
/**
* Read an Endpoint's response if it is ready.
*
* `useCache` guarantees referential equality globally.
* @see https://dataclient.io/docs/api/useCache
*/
export default function useCache(endpoint, ...args) {
const state = useCacheState();
const controller = useController();
const key = args[0] !== null ? endpoint.key(...args) : '';
const cacheResults = key && state.endpoints[key];
const meta = state.meta[key];
// Compute denormalized value
const {
data,
expiryStatus,
expiresAt,
countRef
} = useMemo(() => {
return controller.getResponseMeta(endpoint, ...args, state);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [cacheResults, state.indexes, state.entities, state.entityMeta, meta, key]);
// If we are hard invalid we must fetch regardless of triggering or staleness
const forceFetch = expiryStatus === ExpiryStatus.Invalid;
/*********** This block is to ensure results are only filled when they would not suspend **************/
// This computation reflects the behavior of useSuspense/useFetch
// It only changes the value when expiry or params change.
// This way, random unrelated re-renders don't cause the concept of expiry
// to change
const expired = useMemo(() => {
return (Date.now() > expiresAt || forceFetch) && key;
// we need to check against serialized params, since params can change frequently
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expiresAt, key, forceFetch, state.lastReset]);
// fully "valid" data will not suspend/loading even if it is not fresh
const loading = expiryStatus !== ExpiryStatus.Valid && expired;
/****************************************************************************************************/
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(countRef, [data]);
return useMemo(() => {
// if useSuspense() would suspend, don't include entities from cache
if (loading) {
if (!endpoint.schema) return undefined;
// TODO: use getResponse() once it just returns data
return controller.getResponseMeta(endpoint, ...args, _extends({}, state, {
entities: {}
})).data;
}
return data;
// key substitutes args + endpoint
// we only need cacheResults, as entities are not used in this case
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [key, data, loading, cacheResults]);
/*********************** end block *****************************/
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJFeHBpcnlTdGF0dXMiLCJ1c2VFZmZlY3QiLCJ1c2VNZW1vIiwidXNlQ2FjaGVTdGF0ZSIsInVzZUNvbnRyb2xsZXIiLCJ1c2VDYWNoZSIsImVuZHBvaW50IiwiYXJncyIsInN0YXRlIiwiY29udHJvbGxlciIsImtleSIsImNhY2hlUmVzdWx0cyIsImVuZHBvaW50cyIsIm1ldGEiLCJkYXRhIiwiZXhwaXJ5U3RhdHVzIiwiZXhwaXJlc0F0IiwiY291bnRSZWYiLCJnZXRSZXNwb25zZU1ldGEiLCJpbmRleGVzIiwiZW50aXRpZXMiLCJlbnRpdHlNZXRhIiwiZm9yY2VGZXRjaCIsIkludmFsaWQiLCJleHBpcmVkIiwiRGF0ZSIsIm5vdyIsImxhc3RSZXNldCIsImxvYWRpbmciLCJWYWxpZCIsInNjaGVtYSIsInVuZGVmaW5lZCIsIl9leHRlbmRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hvb2tzL3VzZUNhY2hlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtcbiAgRW5kcG9pbnRJbnRlcmZhY2UsXG4gIERlbm9ybWFsaXplTnVsbGFibGUsXG4gIFNjaGVtYSxcbiAgRmV0Y2hGdW5jdGlvbixcbiAgUmVzb2x2ZVR5cGUsXG4gIE5JLFxufSBmcm9tICdAZGF0YS1jbGllbnQvY29yZSc7XG5pbXBvcnQgeyBFeHBpcnlTdGF0dXMgfSBmcm9tICdAZGF0YS1jbGllbnQvY29yZSc7XG5pbXBvcnQgeyB1c2VFZmZlY3QsIHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbmltcG9ydCB1c2VDYWNoZVN0YXRlIGZyb20gJy4vdXNlQ2FjaGVTdGF0ZS5qcyc7XG5pbXBvcnQgdXNlQ29udHJvbGxlciBmcm9tICcuLi9ob29rcy91c2VDb250cm9sbGVyLmpzJztcblxuLyoqXG4gKiBSZWFkIGFuIEVuZHBvaW50J3MgcmVzcG9uc2UgaWYgaXQgaXMgcmVhZHkuXG4gKlxuICogYHVzZUNhY2hlYCBndWFyYW50ZWVzIHJlZmVyZW50aWFsIGVxdWFsaXR5IGdsb2JhbGx5LlxuICogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vZG9jcy9hcGkvdXNlQ2FjaGVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlQ2FjaGU8XG4gIEUgZXh0ZW5kcyBQaWNrPFxuICAgIEVuZHBvaW50SW50ZXJmYWNlPEZldGNoRnVuY3Rpb24sIFNjaGVtYSB8IHVuZGVmaW5lZCwgdW5kZWZpbmVkIHwgYm9vbGVhbj4sXG4gICAgJ2tleScgfCAnc2NoZW1hJyB8ICdpbnZhbGlkSWZTdGFsZSdcbiAgPixcbj4oXG4gIGVuZHBvaW50OiBFLFxuICAuLi5hcmdzOiByZWFkb25seSBbLi4uUGFyYW1ldGVyczxFWydrZXknXT5dIHwgcmVhZG9ubHkgW251bGxdXG4pOiBFWydzY2hlbWEnXSBleHRlbmRzIHVuZGVmaW5lZCB8IG51bGwgP1xuICBFIGV4dGVuZHMgKC4uLmFyZ3M6IGFueSkgPT4gYW55ID9cbiAgICBSZXNvbHZlVHlwZTxFPiB8IHVuZGVmaW5lZFxuICA6IGFueVxuOiBEZW5vcm1hbGl6ZU51bGxhYmxlPEVbJ3NjaGVtYSddPiB7XG4gIGNvbnN0IHN0YXRlID0gdXNlQ2FjaGVTdGF0ZSgpO1xuICBjb25zdCBjb250cm9sbGVyID0gdXNlQ29udHJvbGxlcigpO1xuXG4gIGNvbnN0IGtleSA9IGFyZ3NbMF0gIT09IG51bGwgPyBlbmRwb2ludC5rZXkoLi4uYXJncykgOiAnJztcbiAgY29uc3QgY2FjaGVSZXN1bHRzID0ga2V5ICYmIHN0YXRlLmVuZHBvaW50c1trZXldO1xuICBjb25zdCBtZXRhID0gc3RhdGUubWV0YVtrZXldO1xuXG4gIC8vIENvbXB1dGUgZGVub3JtYWxpemVkIHZhbHVlXG4gIGNvbnN0IHsgZGF0YSwgZXhwaXJ5U3RhdHVzLCBleHBpcmVzQXQsIGNvdW50UmVmIH0gPSB1c2VNZW1vKCgpID0+IHtcbiAgICByZXR1cm4gY29udHJvbGxlci5nZXRSZXNwb25zZU1ldGEoZW5kcG9pbnQsIC4uLmFyZ3MsIHN0YXRlKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gIH0sIFtcbiAgICBjYWNoZVJlc3VsdHMsXG4gICAgc3RhdGUuaW5kZXhlcyxcbiAgICBzdGF0ZS5lbnRpdGllcyxcbiAgICBzdGF0ZS5lbnRpdHlNZXRhLFxuICAgIG1ldGEsXG4gICAga2V5LFxuICBdKTtcblxuICAvLyBJZiB3ZSBhcmUgaGFyZCBpbnZhbGlkIHdlIG11c3QgZmV0Y2ggcmVnYXJkbGVzcyBvZiB0cmlnZ2VyaW5nIG9yIHN0YWxlbmVzc1xuICBjb25zdCBmb3JjZUZldGNoID0gZXhwaXJ5U3RhdHVzID09PSBFeHBpcnlTdGF0dXMuSW52YWxpZDtcblxuICAvKioqKioqKioqKiogVGhpcyBibG9jayBpcyB0byBlbnN1cmUgcmVzdWx0cyBhcmUgb25seSBmaWxsZWQgd2hlbiB0aGV5IHdvdWxkIG5vdCBzdXNwZW5kICoqKioqKioqKioqKioqL1xuICAvLyBUaGlzIGNvbXB1dGF0aW9uIHJlZmxlY3RzIHRoZSBiZWhhdmlvciBvZiB1c2VTdXNwZW5zZS91c2VGZXRjaFxuICAvLyBJdCBvbmx5IGNoYW5nZXMgdGhlIHZhbHVlIHdoZW4gZXhwaXJ5IG9yIHBhcmFtcyBjaGFuZ2UuXG4gIC8vIFRoaXMgd2F5LCByYW5kb20gdW5yZWxhdGVkIHJlLXJlbmRlcnMgZG9uJ3QgY2F1c2UgdGhlIGNvbmNlcHQgb2YgZXhwaXJ5XG4gIC8vIHRvIGNoYW5nZVxuICBjb25zdCBleHBpcmVkID0gdXNlTWVtbygoKSA9PiB7XG4gICAgcmV0dXJuIChEYXRlLm5vdygpID4gZXhwaXJlc0F0IHx8IGZvcmNlRmV0Y2gpICYmIGtleTtcbiAgICAvLyB3ZSBuZWVkIHRvIGNoZWNrIGFnYWluc3Qgc2VyaWFsaXplZCBwYXJhbXMsIHNpbmNlIHBhcmFtcyBjYW4gY2hhbmdlIGZyZXF1ZW50bHlcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gIH0sIFtleHBpcmVzQXQsIGtleSwgZm9yY2VGZXRjaCwgc3RhdGUubGFzdFJlc2V0XSk7XG5cbiAgLy8gZnVsbHkgXCJ2YWxpZFwiIGRhdGEgd2lsbCBub3Qgc3VzcGVuZC9sb2FkaW5nIGV2ZW4gaWYgaXQgaXMgbm90IGZyZXNoXG4gIGNvbnN0IGxvYWRpbmcgPSBleHBpcnlTdGF0dXMgIT09IEV4cGlyeVN0YXR1cy5WYWxpZCAmJiBleHBpcmVkO1xuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gIHVzZUVmZmVjdChjb3VudFJlZiwgW2RhdGFdKTtcblxuICByZXR1cm4gdXNlTWVtbygoKSA9PiB7XG4gICAgLy8gaWYgdXNlU3VzcGVuc2UoKSB3b3VsZCBzdXNwZW5kLCBkb24ndCBpbmNsdWRlIGVudGl0aWVzIGZyb20gY2FjaGVcbiAgICBpZiAobG9hZGluZykge1xuICAgICAgaWYgKCFlbmRwb2ludC5zY2hlbWEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAvLyBUT0RPOiB1c2UgZ2V0UmVzcG9uc2UoKSBvbmNlIGl0IGp1c3QgcmV0dXJucyBkYXRhXG4gICAgICByZXR1cm4gY29udHJvbGxlci5nZXRSZXNwb25zZU1ldGEoZW5kcG9pbnQsIC4uLmFyZ3MsIHtcbiAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgIGVudGl0aWVzOiB7fSxcbiAgICAgIH0pLmRhdGEgYXMgYW55O1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgICAvLyBrZXkgc3Vic3RpdHV0ZXMgYXJncyArIGVuZHBvaW50XG4gICAgLy8gd2Ugb25seSBuZWVkIGNhY2hlUmVzdWx0cywgYXMgZW50aXRpZXMgYXJlIG5vdCB1c2VkIGluIHRoaXMgY2FzZVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgfSwgW2tleSwgZGF0YSwgbG9hZGluZywgY2FjaGVSZXN1bHRzXSk7XG4gIC8qKioqKioqKioqKioqKioqKioqKioqKiBlbmQgYmxvY2sgKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG59XG4iXSwibWFwcGluZ3MiOiI7QUFRQSxTQUFTQSxZQUFZLFFBQVEsbUJBQW1CO0FBQ2hELFNBQVNDLFNBQVMsRUFBRUMsT0FBTyxRQUFRLE9BQU87QUFFMUMsT0FBT0MsYUFBYSxNQUFNLG9CQUFvQjtBQUM5QyxPQUFPQyxhQUFhLE1BQU0sMkJBQTJCOztBQUVyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLFNBQVNDLFFBQVFBLENBTTlCQyxRQUFXLEVBQ1gsR0FBR0MsSUFBMEQsRUFLNUI7RUFDakMsTUFBTUMsS0FBSyxHQUFHTCxhQUFhLENBQUMsQ0FBQztFQUM3QixNQUFNTSxVQUFVLEdBQUdMLGFBQWEsQ0FBQyxDQUFDO0VBRWxDLE1BQU1NLEdBQUcsR0FBR0gsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksR0FBR0QsUUFBUSxDQUFDSSxHQUFHLENBQUMsR0FBR0gsSUFBSSxDQUFDLEdBQUcsRUFBRTtFQUN6RCxNQUFNSSxZQUFZLEdBQUdELEdBQUcsSUFBSUYsS0FBSyxDQUFDSSxTQUFTLENBQUNGLEdBQUcsQ0FBQztFQUNoRCxNQUFNRyxJQUFJLEdBQUdMLEtBQUssQ0FBQ0ssSUFBSSxDQUFDSCxHQUFHLENBQUM7O0VBRTVCO0VBQ0EsTUFBTTtJQUFFSSxJQUFJO0lBQUVDLFlBQVk7SUFBRUMsU0FBUztJQUFFQztFQUFTLENBQUMsR0FBR2YsT0FBTyxDQUFDLE1BQU07SUFDaEUsT0FBT08sVUFBVSxDQUFDUyxlQUFlLENBQUNaLFFBQVEsRUFBRSxHQUFHQyxJQUFJLEVBQUVDLEtBQUssQ0FBQztJQUMzRDtFQUNGLENBQUMsRUFBRSxDQUNERyxZQUFZLEVBQ1pILEtBQUssQ0FBQ1csT0FBTyxFQUNiWCxLQUFLLENBQUNZLFFBQVEsRUFDZFosS0FBSyxDQUFDYSxVQUFVLEVBQ2hCUixJQUFJLEVBQ0pILEdBQUcsQ0FDSixDQUFDOztFQUVGO0VBQ0EsTUFBTVksVUFBVSxHQUFHUCxZQUFZLEtBQUtmLFlBQVksQ0FBQ3VCLE9BQU87O0VBRXhEO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQSxNQUFNQyxPQUFPLEdBQUd0QixPQUFPLENBQUMsTUFBTTtJQUM1QixPQUFPLENBQUN1QixJQUFJLENBQUNDLEdBQUcsQ0FBQyxDQUFDLEdBQUdWLFNBQVMsSUFBSU0sVUFBVSxLQUFLWixHQUFHO0lBQ3BEO0lBQ0E7RUFDRixDQUFDLEVBQUUsQ0FBQ00sU0FBUyxFQUFFTixHQUFHLEVBQUVZLFVBQVUsRUFBRWQsS0FBSyxDQUFDbUIsU0FBUyxDQUFDLENBQUM7O0VBRWpEO0VBQ0EsTUFBTUMsT0FBTyxHQUFHYixZQUFZLEtBQUtmLFlBQVksQ0FBQzZCLEtBQUssSUFBSUwsT0FBTztFQUM5RDs7RUFFQTtFQUNBdkIsU0FBUyxDQUFDZ0IsUUFBUSxFQUFFLENBQUNILElBQUksQ0FBQyxDQUFDO0VBRTNCLE9BQU9aLE9BQU8sQ0FBQyxNQUFNO0lBQ25CO0lBQ0EsSUFBSTBCLE9BQU8sRUFBRTtNQUNYLElBQUksQ0FBQ3RCLFFBQVEsQ0FBQ3dCLE1BQU0sRUFBRSxPQUFPQyxTQUFTO01BQ3RDO01BQ0EsT0FBT3RCLFVBQVUsQ0FBQ1MsZUFBZSxDQUFDWixRQUFRLEVBQUUsR0FBR0MsSUFBSSxFQUFBeUIsUUFBQSxLQUM5Q3hCLEtBQUs7UUFDUlksUUFBUSxFQUFFLENBQUM7TUFBQyxFQUNiLENBQUMsQ0FBQ04sSUFBSTtJQUNUO0lBQ0EsT0FBT0EsSUFBSTtJQUNYO0lBQ0E7SUFDQTtFQUNGLENBQUMsRUFBRSxDQUFDSixHQUFHLEVBQUVJLElBQUksRUFBRWMsT0FBTyxFQUFFakIsWUFBWSxDQUFDLENBQUM7RUFDdEM7QUFDRiIsImlnbm9yZUxpc3QiOltdfQ==