react-redux-query
Advanced tools
Comparing version 0.8.2 to 0.9.0
{ | ||
"name": "react-redux-query", | ||
"version": "0.8.2", | ||
"version": "0.9.0", | ||
"author": "Kyle Bebak <kylebebak@gmail.com>", | ||
@@ -5,0 +5,0 @@ "description": "React hooks and functions for SWR-style data fetching, backed by Redux", |
39
query.js
@@ -207,2 +207,5 @@ "use strict"; | ||
* fetcher call | ||
* @param options.intervalRedefineFetcher - If true, fetcher is redefined each | ||
* time it's called on interval, by forcing component to rerender (true by | ||
* default) | ||
* @param options.noRefetch - If true, don't refetch if there's already data at | ||
@@ -233,10 +236,11 @@ * key | ||
if (options === void 0) { options = {}; } | ||
var stateKeys = options.stateKeys, compare = options.compare, _a = options.intervalMs, intervalMs = _a === void 0 ? 0 : _a, _b = options.noRefetch, noRefetch = _b === void 0 ? false : _b, _c = options.noRefetchMs, noRefetchMs = _c === void 0 ? 0 : _c, refetchKey = options.refetchKey, updater = options.updater, rest = __rest(options, ["stateKeys", "compare", "intervalMs", "noRefetch", "noRefetchMs", "refetchKey", "updater"]); | ||
var stateKeys = options.stateKeys, compare = options.compare, _a = options.intervalMs, intervalMs = _a === void 0 ? 0 : _a, _b = options.intervalRedefineFetcher, intervalRedefineFetcher = _b === void 0 ? true : _b, _c = options.noRefetch, noRefetch = _c === void 0 ? false : _c, _d = options.noRefetchMs, noRefetchMs = _d === void 0 ? 0 : _d, refetchKey = options.refetchKey, updater = options.updater, rest = __rest(options, ["stateKeys", "compare", "intervalMs", "intervalRedefineFetcher", "noRefetch", "noRefetchMs", "refetchKey", "updater"]); | ||
var config = react_1.useContext(exports.ConfigContext); | ||
var dispatch = react_redux_1.useDispatch(); | ||
var intervalId = react_1.useRef(0); | ||
var _e = react_1.useState(0), intervalId = _e[0], setIntervalId = _e[1]; | ||
var intervalTimeoutIdRef = react_1.useRef(); | ||
var queryState = useQueryState(key, { stateKeys: stateKeys, compare: compare }); | ||
react_1.useEffect(function () { | ||
// Clear previous interval, create id for new interval | ||
intervalId.current = intervalId.current + 1; | ||
// If we have pending interval call to query, clear it; we're about to query again anyway | ||
clearTimeout(intervalTimeoutIdRef.current); | ||
// Should we return early? | ||
@@ -253,16 +257,17 @@ if (queryState.data && noRefetch) { | ||
return; | ||
var doQuery = function (id) { return __awaiter(_this, void 0, void 0, function () { | ||
var doQuery = function () { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (intervalMs > 0 && intervalId.current !== id) | ||
return [2 /*return*/]; | ||
return [4 /*yield*/, query(key, fetcher, __assign(__assign(__assign({}, config), rest), { updater: updater, dispatch: dispatch })) | ||
// "pseudo-recursive" interval call means call stack doesn't grow: https://stackoverflow.com/questions/48736331 | ||
]; | ||
case 0: return [4 /*yield*/, query(key, fetcher, __assign(__assign(__assign({}, config), rest), { updater: updater, dispatch: dispatch }))]; | ||
case 1: | ||
_a.sent(); | ||
// "pseudo-recursive" interval call means call stack doesn't grow: https://stackoverflow.com/questions/48736331 | ||
if (intervalMs > 0) | ||
setTimeout(function () { return doQuery(id); }, intervalMs); | ||
if (intervalMs <= 0) | ||
return [2 /*return*/]; | ||
// Force this effect to run again after intervalMs; "pseudo-recursive" call means call stack doesn't grow | ||
intervalTimeoutIdRef.current = window.setTimeout(function () { | ||
if (intervalRedefineFetcher) | ||
setIntervalId(function (id) { return id + 1; }); | ||
else | ||
doQuery(); | ||
}, intervalMs); | ||
return [2 /*return*/]; | ||
@@ -272,8 +277,8 @@ } | ||
}); }; | ||
doQuery(intervalId.current); | ||
}, [key, intervalMs, refetchKey]); // eslint-disable-line | ||
doQuery(); | ||
}, [key, intervalMs, intervalRedefineFetcher, refetchKey, intervalId]); // eslint-disable-line | ||
// Also clear interval when component unmounts | ||
react_1.useEffect(function () { | ||
return function () { | ||
intervalId.current = -1; | ||
clearTimeout(intervalTimeoutIdRef.current); | ||
}; | ||
@@ -280,0 +285,0 @@ }, []); |
42
query.ts
@@ -1,2 +0,2 @@ | ||
import { createContext, useContext, useEffect, useRef } from 'react' | ||
import { createContext, useContext, useEffect, useRef, useState } from 'react' | ||
import { batch, shallowEqual, useDispatch, useSelector } from 'react-redux' | ||
@@ -181,2 +181,5 @@ import { Dispatch } from 'redux' | ||
* fetcher call | ||
* @param options.intervalRedefineFetcher - If true, fetcher is redefined each | ||
* time it's called on interval, by forcing component to rerender (true by | ||
* default) | ||
* @param options.noRefetch - If true, don't refetch if there's already data at | ||
@@ -208,3 +211,9 @@ * key | ||
options: QueryOptions<D> & | ||
QueryStateOptions<K, D> & { intervalMs?: number; noRefetch?: boolean; noRefetchMs?: number; refetchKey?: any } = {}, | ||
QueryStateOptions<K, D> & { | ||
intervalMs?: number | ||
intervalRedefineFetcher?: boolean | ||
noRefetch?: boolean | ||
noRefetchMs?: number | ||
refetchKey?: any | ||
} = {}, | ||
) { | ||
@@ -215,2 +224,3 @@ const { | ||
intervalMs = 0, | ||
intervalRedefineFetcher = true, | ||
noRefetch = false, | ||
@@ -223,10 +233,12 @@ noRefetchMs = 0, | ||
const config = useContext(ConfigContext) | ||
const dispatch = useDispatch() | ||
const dispatch = useDispatch() | ||
const intervalId = useRef(0) | ||
const [intervalId, setIntervalId] = useState(0) | ||
const intervalTimeoutIdRef = useRef<number>() | ||
const queryState = useQueryState<K, D>(key, { stateKeys, compare }) | ||
useEffect(() => { | ||
// Clear previous interval, create id for new interval | ||
intervalId.current = intervalId.current + 1 | ||
// If we have pending interval call to query, clear it; we're about to query again anyway | ||
clearTimeout(intervalTimeoutIdRef.current) | ||
@@ -242,11 +254,15 @@ // Should we return early? | ||
const doQuery = async (id: number) => { | ||
if (intervalMs > 0 && intervalId.current !== id) return | ||
const doQuery = async () => { | ||
await query(key, fetcher, { ...config, ...rest, updater: updater as QueryOptions<any>['updater'], dispatch }) | ||
// "pseudo-recursive" interval call means call stack doesn't grow: https://stackoverflow.com/questions/48736331 | ||
if (intervalMs > 0) setTimeout(() => doQuery(id), intervalMs) | ||
if (intervalMs <= 0) return | ||
// Force this effect to run again after intervalMs; "pseudo-recursive" call means call stack doesn't grow | ||
intervalTimeoutIdRef.current = window.setTimeout(() => { | ||
if (intervalRedefineFetcher) setIntervalId((id) => id + 1) | ||
else doQuery() | ||
}, intervalMs) | ||
} | ||
doQuery(intervalId.current) | ||
}, [key, intervalMs, refetchKey]) // eslint-disable-line | ||
doQuery() | ||
}, [key, intervalMs, intervalRedefineFetcher, refetchKey, intervalId]) // eslint-disable-line | ||
@@ -256,3 +272,3 @@ // Also clear interval when component unmounts | ||
return () => { | ||
intervalId.current = -1 | ||
clearTimeout(intervalTimeoutIdRef.current) | ||
} | ||
@@ -259,0 +275,0 @@ }, []) |
@@ -91,2 +91,4 @@ # react-redux-query | ||
When polling, to ensure the fetcher is redefined each time it's called, `useQuery` updates a piece of state that forces its component to rerender. If you have a fetcher that only needs to be defined once, and you want to avoid an extra rerender each time it's called, pass `false` for `intervalRedefineFetcher` in the options. | ||
### `query` function | ||
@@ -159,2 +161,3 @@ | ||
- `intervalMs`: Interval between end of fetcher call and next fetcher call | ||
- `intervalRedefineFetcher`: If true, fetcher is redefined each time it's called on interval, by forcing component to rerender (true by default) | ||
- `noRefetch`: If true, don't refetch if there's already data at key | ||
@@ -161,0 +164,0 @@ - `noRefetchMs`: If noRefetch is true, noRefetch behavior active for this many ms (forever by default) |
53667
906
231