react-async-hook
Advanced tools
Comparing version 3.5.3 to 3.6.0
@@ -30,2 +30,3 @@ declare type UnknownResult = unknown; | ||
set: (value: AsyncState<R>) => void; | ||
merge: (value: Partial<AsyncState<R>>) => void; | ||
reset: () => void; | ||
@@ -43,2 +44,12 @@ execute: (...args: Args) => Promise<R>; | ||
export declare const useAsyncCallback: <R = unknown, Args extends any[] = any[]>(asyncFunction: (...args: Args) => MaybePromise<R>, options?: UseAsyncCallbackOptions<R>) => UseAsyncReturn<R, Args>; | ||
export declare const useAsyncFetchMore: <R, Args extends any[]>({ value, fetchMore, merge, }: { | ||
value: UseAsyncReturn<R, Args>; | ||
fetchMore: (result: R) => Promise<R>; | ||
merge: (result: R, moreResult: R) => R; | ||
}) => { | ||
canFetchMore: boolean; | ||
loading: boolean; | ||
status: AsyncStateStatus; | ||
fetchMore: () => Promise<R>; | ||
}; | ||
export {}; |
@@ -42,2 +42,17 @@ 'use strict'; | ||
var useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? react.useLayoutEffect : react.useEffect; // assign current value to a ref and providing a getter. | ||
// This way we are sure to always get latest value provided to hook and | ||
// avoid weird issues due to closures capturing stale values... | ||
// See https://overreacted.io/making-setinterval-declarative-with-react-hooks/ | ||
var useGetter = function useGetter(t) { | ||
var ref = react.useRef(t); | ||
useIsomorphicLayoutEffect(function () { | ||
ref.current = t; | ||
}); | ||
return function () { | ||
return ref.current; | ||
}; | ||
}; | ||
var InitialAsyncState = { | ||
@@ -116,5 +131,10 @@ status: 'not-requested', | ||
}, [value, setValue]); | ||
var set = setValue; | ||
var merge = react.useCallback(function (state) { | ||
return set(_extends({}, value, {}, state)); | ||
}, [value, set]); | ||
return { | ||
value: value, | ||
set: setValue, | ||
set: set, | ||
merge: merge, | ||
reset: reset, | ||
@@ -226,2 +246,3 @@ setLoading: setLoading, | ||
set: AsyncState.set, | ||
merge: AsyncState.merge, | ||
reset: AsyncState.reset, | ||
@@ -282,6 +303,58 @@ execute: executeAsyncOperation, | ||
}; | ||
var useAsyncFetchMore = function useAsyncFetchMore(_ref) { | ||
var value = _ref.value, | ||
fetchMore = _ref.fetchMore, | ||
merge = _ref.merge; | ||
var getAsyncValue = useGetter(value); | ||
var fetchMoreAsync = useAsyncCallback(function () { | ||
try { | ||
var freshAsyncValue = getAsyncValue(); | ||
if (freshAsyncValue.status !== 'success') { | ||
throw new Error("Can't fetch more if the original fetch is not a success"); | ||
} | ||
if (fetchMoreAsync.status === 'loading') { | ||
throw new Error("Can't fetch more, because we are already fetching more!"); | ||
} | ||
return Promise.resolve(fetchMore(freshAsyncValue.result)).then(function (moreResult) { | ||
// Handle race conditions: we only merge the fetchMore result if the initial async value is the same | ||
// TODO not satisfied with this, we should just use "freshAsyncValue === getAsyncValue()" but asyncValue is not "stable" | ||
var canMerge = freshAsyncValue.status === getAsyncValue().status && freshAsyncValue.result === getAsyncValue().result; | ||
if (canMerge) { | ||
value.merge({ | ||
result: merge(value.result, moreResult) | ||
}); | ||
} // return is useful for chaining, like fetchMore().then(result => {}); | ||
return moreResult; | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
}); // We only allow to fetch more on a stable async value | ||
// If that value change for whatever reason, we reset the fetchmore too (which will make current pending requests to be ignored) | ||
// TODO value is not stable, we could just reset on value change otherwise | ||
var shouldReset = value.status !== 'success'; | ||
react.useEffect(function () { | ||
if (shouldReset) { | ||
fetchMoreAsync.reset(); | ||
} | ||
}, [shouldReset]); | ||
return { | ||
canFetchMore: value.status === 'success' && fetchMoreAsync.status !== 'loading', | ||
loading: fetchMoreAsync.loading, | ||
status: fetchMoreAsync.status, | ||
fetchMore: fetchMoreAsync.execute | ||
}; | ||
}; | ||
exports.useAsync = useAsync; | ||
exports.useAsyncAbortable = useAsyncAbortable; | ||
exports.useAsyncCallback = useAsyncCallback; | ||
exports.useAsyncFetchMore = useAsyncFetchMore; | ||
//# sourceMappingURL=react-async-hook.cjs.development.js.map |
@@ -1,2 +0,2 @@ | ||
"use strict";var r=require("react");function t(){return(t=Object.assign||function(r){for(var t=1;t<arguments.length;t++){var e=arguments[t];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n])}return r}).apply(this,arguments)}"undefined"!=typeof Symbol&&(Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator"))),"undefined"!=typeof Symbol&&(Symbol.asyncIterator||(Symbol.asyncIterator=Symbol("Symbol.asyncIterator")));var e={status:"not-requested",loading:!1,result:void 0,error:void 0},n={status:"loading",loading:!0,result:void 0,error:void 0},u=function(){},o={initialState:function(r){return r&&r.executeOnMount?n:e},executeOnMount:!0,executeOnUpdate:!0,setLoading:function(r){return n},setResult:function(r,t){return{status:"success",loading:!1,result:r,error:void 0}},setError:function(r,t){return{status:"error",loading:!1,result:void 0,error:r}},onSuccess:u,onError:u},s=function(e,n,u){var s,i=function(r){return t({},o,{},r)}(u),c=r.useState(null),a=c[0],l=c[1],f=function(t){var e=r.useState(function(){return t.initialState(t)}),n=e[0],u=e[1],o=r.useCallback(function(){return u(t.initialState(t))},[u,t]),s=r.useCallback(function(){return u(t.setLoading(n))},[n,u]),i=r.useCallback(function(r){return u(t.setResult(r,n))},[n,u]),c=r.useCallback(function(r){return u(t.setError(r,n))},[n,u]);return{value:n,set:u,reset:o,setLoading:s,setResult:i,setError:c}}(i),v=(s=r.useRef(!1),r.useEffect(function(){return s.current=!0,function(){s.current=!1}},[]),function(){return s.current}),d=function(){var t=r.useRef(null);return{set:function(r){return t.current=r},get:function(){return t.current},is:function(r){return t.current===r}}}(),y=function(r){return v()&&d.is(r)},b=function(){for(var r=arguments.length,t=new Array(r),n=0;n<r;n++)t[n]=arguments[n];var u=e.apply(void 0,t);if(l(t),u instanceof Promise)return d.set(u),f.setLoading(),u.then(function(r){y(u)&&f.setResult(r),i.onSuccess(r,{isCurrent:function(){return d.is(u)}})},function(r){y(u)&&f.setError(r),i.onError(r,{isCurrent:function(){return d.is(u)}})}),u;var o=u;return f.setResult(o),Promise.resolve(o)},p=!v();return r.useEffect(function(){p?i.executeOnMount&&b.apply(void 0,n):i.executeOnUpdate&&b.apply(void 0,n)},n),t({},f.value,{set:f.set,reset:f.reset,execute:b,currentPromise:d.get(),currentParams:a})};function i(r,t,e){return s(r,t,e)}exports.useAsync=i,exports.useAsyncAbortable=function(t,e,n){var u=r.useRef();return i(function(){for(var r=arguments.length,e=new Array(r),n=0;n<r;n++)e[n]=arguments[n];try{u.current&&u.current.abort();var o=new AbortController;return u.current=o,Promise.resolve(function(r,n){try{var u=Promise.resolve(t.apply(void 0,[o.signal].concat(e)))}catch(r){return n(!0,r)}return u&&u.then?u.then(n.bind(null,!1),n.bind(null,!0)):n(!1,value)}(0,function(r,t){if(u.current===o&&(u.current=void 0),r)throw t;return t}))}catch(r){return Promise.reject(r)}},e,n)},exports.useAsyncCallback=function(r,e){return s(r,[],t({},e,{executeOnMount:!1,executeOnUpdate:!1}))}; | ||
"use strict";var e=require("react");function t(){return(t=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}"undefined"!=typeof Symbol&&(Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator"))),"undefined"!=typeof Symbol&&(Symbol.asyncIterator||(Symbol.asyncIterator=Symbol("Symbol.asyncIterator")));var r="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?e.useLayoutEffect:e.useEffect,n={status:"not-requested",loading:!1,result:void 0,error:void 0},u={status:"loading",loading:!0,result:void 0,error:void 0},o=function(){},s={initialState:function(e){return e&&e.executeOnMount?u:n},executeOnMount:!0,executeOnUpdate:!0,setLoading:function(e){return u},setResult:function(e,t){return{status:"success",loading:!1,result:e,error:void 0}},setError:function(e,t){return{status:"error",loading:!1,result:void 0,error:e}},onSuccess:o,onError:o},c=function(r,n,u){var o,c=function(e){return t({},s,{},e)}(u),i=e.useState(null),a=i[0],l=i[1],f=function(r){var n=e.useState(function(){return r.initialState(r)}),u=n[0],o=n[1],s=e.useCallback(function(){return o(r.initialState(r))},[o,r]),c=e.useCallback(function(){return o(r.setLoading(u))},[u,o]),i=e.useCallback(function(e){return o(r.setResult(e,u))},[u,o]),a=e.useCallback(function(e){return o(r.setError(e,u))},[u,o]),l=o,f=e.useCallback(function(e){return l(t({},u,{},e))},[u,l]);return{value:u,set:l,merge:f,reset:s,setLoading:c,setResult:i,setError:a}}(c),d=(o=e.useRef(!1),e.useEffect(function(){return o.current=!0,function(){o.current=!1}},[]),function(){return o.current}),v=function(){var t=e.useRef(null);return{set:function(e){return t.current=e},get:function(){return t.current},is:function(e){return t.current===e}}}(),y=function(e){return d()&&v.is(e)},m=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var u=r.apply(void 0,t);if(l(t),u instanceof Promise)return v.set(u),f.setLoading(),u.then(function(e){y(u)&&f.setResult(e),c.onSuccess(e,{isCurrent:function(){return v.is(u)}})},function(e){y(u)&&f.setError(e),c.onError(e,{isCurrent:function(){return v.is(u)}})}),u;var o=u;return f.setResult(o),Promise.resolve(o)},g=!d();return e.useEffect(function(){g?c.executeOnMount&&m.apply(void 0,n):c.executeOnUpdate&&m.apply(void 0,n)},n),t({},f.value,{set:f.set,merge:f.merge,reset:f.reset,execute:m,currentPromise:v.get(),currentParams:a})};function i(e,t,r){return c(e,t,r)}var a=function(e,r){return c(e,[],t({},r,{executeOnMount:!1,executeOnUpdate:!1}))};exports.useAsync=i,exports.useAsyncAbortable=function(t,r,n){var u=e.useRef();return i(function(){for(var e=arguments.length,r=new Array(e),n=0;n<e;n++)r[n]=arguments[n];try{u.current&&u.current.abort();var o=new AbortController;return u.current=o,Promise.resolve(function(e,n){try{var u=Promise.resolve(t.apply(void 0,[o.signal].concat(r)))}catch(e){return n(!0,e)}return u&&u.then?u.then(n.bind(null,!1),n.bind(null,!0)):n(!1,value)}(0,function(e,t){if(u.current===o&&(u.current=void 0),e)throw t;return t}))}catch(e){return Promise.reject(e)}},r,n)},exports.useAsyncCallback=a,exports.useAsyncFetchMore=function(t){var n,u,o=t.value,s=t.fetchMore,c=t.merge,i=(u=e.useRef(n=o),r(function(){u.current=n}),function(){return u.current}),l=a(function(){try{var e=i();if("success"!==e.status)throw new Error("Can't fetch more if the original fetch is not a success");if("loading"===l.status)throw new Error("Can't fetch more, because we are already fetching more!");return Promise.resolve(s(e.result)).then(function(t){return e.status===i().status&&e.result===i().result&&o.merge({result:c(o.result,t)}),t})}catch(e){return Promise.reject(e)}}),f="success"!==o.status;return e.useEffect(function(){f&&l.reset()},[f]),{canFetchMore:"success"===o.status&&"loading"!==l.status,loading:l.loading,status:l.status,fetchMore:l.execute}}; | ||
//# sourceMappingURL=react-async-hook.cjs.production.min.js.map |
@@ -1,2 +0,2 @@ | ||
import { useRef, useState, useEffect, useCallback } from 'react'; | ||
import { useLayoutEffect, useEffect, useRef, useState, useCallback } from 'react'; | ||
@@ -40,2 +40,17 @@ function _extends() { | ||
var useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? useLayoutEffect : useEffect; // assign current value to a ref and providing a getter. | ||
// This way we are sure to always get latest value provided to hook and | ||
// avoid weird issues due to closures capturing stale values... | ||
// See https://overreacted.io/making-setinterval-declarative-with-react-hooks/ | ||
var useGetter = function useGetter(t) { | ||
var ref = useRef(t); | ||
useIsomorphicLayoutEffect(function () { | ||
ref.current = t; | ||
}); | ||
return function () { | ||
return ref.current; | ||
}; | ||
}; | ||
var InitialAsyncState = { | ||
@@ -114,5 +129,10 @@ status: 'not-requested', | ||
}, [value, setValue]); | ||
var set = setValue; | ||
var merge = useCallback(function (state) { | ||
return set(_extends({}, value, {}, state)); | ||
}, [value, set]); | ||
return { | ||
value: value, | ||
set: setValue, | ||
set: set, | ||
merge: merge, | ||
reset: reset, | ||
@@ -224,2 +244,3 @@ setLoading: setLoading, | ||
set: AsyncState.set, | ||
merge: AsyncState.merge, | ||
reset: AsyncState.reset, | ||
@@ -280,4 +301,55 @@ execute: executeAsyncOperation, | ||
}; | ||
var useAsyncFetchMore = function useAsyncFetchMore(_ref) { | ||
var value = _ref.value, | ||
fetchMore = _ref.fetchMore, | ||
merge = _ref.merge; | ||
var getAsyncValue = useGetter(value); | ||
var fetchMoreAsync = useAsyncCallback(function () { | ||
try { | ||
var freshAsyncValue = getAsyncValue(); | ||
export { useAsync, useAsyncAbortable, useAsyncCallback }; | ||
if (freshAsyncValue.status !== 'success') { | ||
throw new Error("Can't fetch more if the original fetch is not a success"); | ||
} | ||
if (fetchMoreAsync.status === 'loading') { | ||
throw new Error("Can't fetch more, because we are already fetching more!"); | ||
} | ||
return Promise.resolve(fetchMore(freshAsyncValue.result)).then(function (moreResult) { | ||
// Handle race conditions: we only merge the fetchMore result if the initial async value is the same | ||
// TODO not satisfied with this, we should just use "freshAsyncValue === getAsyncValue()" but asyncValue is not "stable" | ||
var canMerge = freshAsyncValue.status === getAsyncValue().status && freshAsyncValue.result === getAsyncValue().result; | ||
if (canMerge) { | ||
value.merge({ | ||
result: merge(value.result, moreResult) | ||
}); | ||
} // return is useful for chaining, like fetchMore().then(result => {}); | ||
return moreResult; | ||
}); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
}); // We only allow to fetch more on a stable async value | ||
// If that value change for whatever reason, we reset the fetchmore too (which will make current pending requests to be ignored) | ||
// TODO value is not stable, we could just reset on value change otherwise | ||
var shouldReset = value.status !== 'success'; | ||
useEffect(function () { | ||
if (shouldReset) { | ||
fetchMoreAsync.reset(); | ||
} | ||
}, [shouldReset]); | ||
return { | ||
canFetchMore: value.status === 'success' && fetchMoreAsync.status !== 'loading', | ||
loading: fetchMoreAsync.loading, | ||
status: fetchMoreAsync.status, | ||
fetchMore: fetchMoreAsync.execute | ||
}; | ||
}; | ||
export { useAsync, useAsyncAbortable, useAsyncCallback, useAsyncFetchMore }; | ||
//# sourceMappingURL=react-async-hook.esm.js.map |
{ | ||
"name": "react-async-hook", | ||
"version": "3.5.3", | ||
"version": "3.6.0", | ||
"description": "Async hook", | ||
@@ -5,0 +5,0 @@ "author": "Sébastien Lorber", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
169949
686