@khanacademy/wonder-blocks-data 15.0.2 → 15.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/es/index.js +2 -2
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-data
|
|
2
2
|
|
|
3
|
+
## 15.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0d4e856: Fix `useCachedEffect` refetching forever when an unmemoized `onResultChanged` callback is passed with the `CacheAndNetwork` or `NetworkOnly` fetch policies. The callback is now tracked via a latest-value ref so its identity no longer invalidates the memoized fetch function (which cancelled the inflight request and restarted the fetch); the most recently supplied callback is still the one invoked when a result arrives.
|
|
8
|
+
|
|
3
9
|
## 15.0.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, useForceUpdate } from '@khanacademy/wonder-blocks-core';
|
|
1
|
+
import { Server, useForceUpdate, useLatestRef } from '@khanacademy/wonder-blocks-core';
|
|
2
2
|
import { KindError, clone, entries } from '@khanacademy/wonder-stuff-core';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { useContext, useRef, useMemo, useCallback } from 'react';
|
|
@@ -38,7 +38,7 @@ const useRequestInterception=(requestId,handler)=>{const interceptors=React.useC
|
|
|
38
38
|
|
|
39
39
|
const useServerEffect=(requestId,handler,options={})=>{const{hydrate=true,skip=false}=options;const interceptedHandler=useRequestInterception(requestId,handler);const cachedResult=SsrCache.Default.getEntry(requestId);const maybeTrack=useContext(TrackerContext);if(!skip&&cachedResult==null&&Server.isServerSide()){maybeTrack?.(requestId,interceptedHandler,hydrate);}return cachedResult==null?null:resultFromCachedResponse(cachedResult)};
|
|
40
40
|
|
|
41
|
-
const DefaultScope$1="useCachedEffect";const useCachedEffect=(requestId,handler,options={})=>{const{fetchPolicy=FetchPolicy.CacheBeforeNetwork,skip:hardSkip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope$1}=options;const interceptedHandler=useRequestInterception(requestId,handler);const[mostRecentResult,setMostRecentResult]=useSharedCache(requestId,scope);const forceUpdate=useForceUpdate();const networkResultRef=React.useRef();const currentRequestRef=React.useRef();const fetchRequest=React.useMemo(()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;networkResultRef.current=null;const fetchFn=()=>{if(fetchPolicy===FetchPolicy.CacheOnly){throw new DataError("Cannot fetch with CacheOnly policy",DataErrors.NotAllowed)}const request=RequestFulfillment.Default.fulfill(`${requestId}|${scope}`,{handler:interceptedHandler});if(request===currentRequestRef.current?.request){return}networkResultRef.current=null;currentRequestRef.current?.cancel();let cancel=false;request.then(result=>{currentRequestRef.current=null;if(cancel){return}setMostRecentResult(result);networkResultRef.current=result;if(onResultChanged!=null){onResultChanged(result);}else {forceUpdate();}return});currentRequestRef.current={requestId,request,cancel(){cancel=true;RequestFulfillment.Default.abort(requestId);}};};return fetchFn},[requestId,
|
|
41
|
+
const DefaultScope$1="useCachedEffect";const useCachedEffect=(requestId,handler,options={})=>{const{fetchPolicy=FetchPolicy.CacheBeforeNetwork,skip:hardSkip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope$1}=options;const interceptedHandler=useRequestInterception(requestId,handler);const[mostRecentResult,setMostRecentResult]=useSharedCache(requestId,scope);const forceUpdate=useForceUpdate();const onResultChangedRef=useLatestRef(onResultChanged);const networkResultRef=React.useRef();const currentRequestRef=React.useRef();const fetchRequest=React.useMemo(()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;networkResultRef.current=null;const fetchFn=()=>{if(fetchPolicy===FetchPolicy.CacheOnly){throw new DataError("Cannot fetch with CacheOnly policy",DataErrors.NotAllowed)}const request=RequestFulfillment.Default.fulfill(`${requestId}|${scope}`,{handler:interceptedHandler});if(request===currentRequestRef.current?.request){return}networkResultRef.current=null;currentRequestRef.current?.cancel();let cancel=false;request.then(result=>{currentRequestRef.current=null;if(cancel){return}setMostRecentResult(result);networkResultRef.current=result;const onResultChanged=onResultChangedRef.current;if(onResultChanged!=null){onResultChanged(result);}else {forceUpdate();}return});currentRequestRef.current={requestId,request,cancel(){cancel=true;RequestFulfillment.Default.abort(requestId);}};};return fetchFn},[requestId,forceUpdate,setMostRecentResult,fetchPolicy]);const shouldFetch=React.useMemo(()=>{if(hardSkip){return false}switch(fetchPolicy){case FetchPolicy.CacheOnly:return false;case FetchPolicy.CacheBeforeNetwork:return mostRecentResult==null;case FetchPolicy.CacheAndNetwork:case FetchPolicy.NetworkOnly:return networkResultRef.current==null}},[mostRecentResult,fetchPolicy,hardSkip]);React.useEffect(()=>{if(!shouldFetch){return}fetchRequest();return ()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;}},[shouldFetch,fetchRequest]);const lastResultAgnosticOfIdRef=React.useRef(Status.noData());const loadingResult=retainResultOnChange?lastResultAgnosticOfIdRef.current:shouldFetch?Status.loading():Status.noData();const result=(fetchPolicy===FetchPolicy.NetworkOnly?networkResultRef.current:mostRecentResult)??loadingResult;lastResultAgnosticOfIdRef.current=result;return [result,fetchRequest]};
|
|
42
42
|
|
|
43
43
|
var WhenClientSide=/*#__PURE__*/function(WhenClientSide){WhenClientSide["DoNotHydrate"]="DoNotHydrate";WhenClientSide["ExecuteWhenNoResult"]="ExecuteWhenNoResult";WhenClientSide["ExecuteWhenNoSuccessResult"]="ExecuteWhenNoSuccessResult";WhenClientSide["AlwaysExecute"]="AlwaysExecute";return WhenClientSide}({});const DefaultScope="useHydratableEffect";const useHydratableEffect=(requestId,handler,options={})=>{const{clientBehavior="ExecuteWhenNoSuccessResult",skip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope}=options;const serverResult=useServerEffect(requestId,handler,{hydrate:clientBehavior!=="DoNotHydrate",skip});const getDefaultCacheValue=React.useCallback(()=>{switch(clientBehavior){case"DoNotHydrate":case"AlwaysExecute":return null;case"ExecuteWhenNoResult":return serverResult;case"ExecuteWhenNoSuccessResult":if(serverResult?.status==="success"){return serverResult}return null}},[serverResult]);useSharedCache(requestId,scope,getDefaultCacheValue);const[clientResult]=useCachedEffect(requestId,handler,{skip,onResultChanged,retainResultOnChange,scope,fetchPolicy:FetchPolicy.CacheBeforeNetwork});return serverResult??clientResult};
|
|
44
44
|
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ const useRequestInterception=(requestId,handler)=>{const interceptors=React__nam
|
|
|
61
61
|
|
|
62
62
|
const useServerEffect=(requestId,handler,options={})=>{const{hydrate=true,skip=false}=options;const interceptedHandler=useRequestInterception(requestId,handler);const cachedResult=SsrCache.Default.getEntry(requestId);const maybeTrack=React.useContext(TrackerContext);if(!skip&&cachedResult==null&&wonderBlocksCore.Server.isServerSide()){maybeTrack?.(requestId,interceptedHandler,hydrate);}return cachedResult==null?null:resultFromCachedResponse(cachedResult)};
|
|
63
63
|
|
|
64
|
-
const DefaultScope$1="useCachedEffect";const useCachedEffect=(requestId,handler,options={})=>{const{fetchPolicy=FetchPolicy.CacheBeforeNetwork,skip:hardSkip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope$1}=options;const interceptedHandler=useRequestInterception(requestId,handler);const[mostRecentResult,setMostRecentResult]=useSharedCache(requestId,scope);const forceUpdate=wonderBlocksCore.useForceUpdate();const networkResultRef=React__namespace.useRef();const currentRequestRef=React__namespace.useRef();const fetchRequest=React__namespace.useMemo(()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;networkResultRef.current=null;const fetchFn=()=>{if(fetchPolicy===FetchPolicy.CacheOnly){throw new DataError("Cannot fetch with CacheOnly policy",DataErrors.NotAllowed)}const request=RequestFulfillment.Default.fulfill(`${requestId}|${scope}`,{handler:interceptedHandler});if(request===currentRequestRef.current?.request){return}networkResultRef.current=null;currentRequestRef.current?.cancel();let cancel=false;request.then(result=>{currentRequestRef.current=null;if(cancel){return}setMostRecentResult(result);networkResultRef.current=result;if(onResultChanged!=null){onResultChanged(result);}else {forceUpdate();}return});currentRequestRef.current={requestId,request,cancel(){cancel=true;RequestFulfillment.Default.abort(requestId);}};};return fetchFn},[requestId,
|
|
64
|
+
const DefaultScope$1="useCachedEffect";const useCachedEffect=(requestId,handler,options={})=>{const{fetchPolicy=FetchPolicy.CacheBeforeNetwork,skip:hardSkip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope$1}=options;const interceptedHandler=useRequestInterception(requestId,handler);const[mostRecentResult,setMostRecentResult]=useSharedCache(requestId,scope);const forceUpdate=wonderBlocksCore.useForceUpdate();const onResultChangedRef=wonderBlocksCore.useLatestRef(onResultChanged);const networkResultRef=React__namespace.useRef();const currentRequestRef=React__namespace.useRef();const fetchRequest=React__namespace.useMemo(()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;networkResultRef.current=null;const fetchFn=()=>{if(fetchPolicy===FetchPolicy.CacheOnly){throw new DataError("Cannot fetch with CacheOnly policy",DataErrors.NotAllowed)}const request=RequestFulfillment.Default.fulfill(`${requestId}|${scope}`,{handler:interceptedHandler});if(request===currentRequestRef.current?.request){return}networkResultRef.current=null;currentRequestRef.current?.cancel();let cancel=false;request.then(result=>{currentRequestRef.current=null;if(cancel){return}setMostRecentResult(result);networkResultRef.current=result;const onResultChanged=onResultChangedRef.current;if(onResultChanged!=null){onResultChanged(result);}else {forceUpdate();}return});currentRequestRef.current={requestId,request,cancel(){cancel=true;RequestFulfillment.Default.abort(requestId);}};};return fetchFn},[requestId,forceUpdate,setMostRecentResult,fetchPolicy]);const shouldFetch=React__namespace.useMemo(()=>{if(hardSkip){return false}switch(fetchPolicy){case FetchPolicy.CacheOnly:return false;case FetchPolicy.CacheBeforeNetwork:return mostRecentResult==null;case FetchPolicy.CacheAndNetwork:case FetchPolicy.NetworkOnly:return networkResultRef.current==null}},[mostRecentResult,fetchPolicy,hardSkip]);React__namespace.useEffect(()=>{if(!shouldFetch){return}fetchRequest();return ()=>{currentRequestRef.current?.cancel();currentRequestRef.current=null;}},[shouldFetch,fetchRequest]);const lastResultAgnosticOfIdRef=React__namespace.useRef(Status.noData());const loadingResult=retainResultOnChange?lastResultAgnosticOfIdRef.current:shouldFetch?Status.loading():Status.noData();const result=(fetchPolicy===FetchPolicy.NetworkOnly?networkResultRef.current:mostRecentResult)??loadingResult;lastResultAgnosticOfIdRef.current=result;return [result,fetchRequest]};
|
|
65
65
|
|
|
66
66
|
var WhenClientSide=/*#__PURE__*/function(WhenClientSide){WhenClientSide["DoNotHydrate"]="DoNotHydrate";WhenClientSide["ExecuteWhenNoResult"]="ExecuteWhenNoResult";WhenClientSide["ExecuteWhenNoSuccessResult"]="ExecuteWhenNoSuccessResult";WhenClientSide["AlwaysExecute"]="AlwaysExecute";return WhenClientSide}({});const DefaultScope="useHydratableEffect";const useHydratableEffect=(requestId,handler,options={})=>{const{clientBehavior="ExecuteWhenNoSuccessResult",skip=false,retainResultOnChange=false,onResultChanged,scope=DefaultScope}=options;const serverResult=useServerEffect(requestId,handler,{hydrate:clientBehavior!=="DoNotHydrate",skip});const getDefaultCacheValue=React__namespace.useCallback(()=>{switch(clientBehavior){case"DoNotHydrate":case"AlwaysExecute":return null;case"ExecuteWhenNoResult":return serverResult;case"ExecuteWhenNoSuccessResult":if(serverResult?.status==="success"){return serverResult}return null}},[serverResult]);useSharedCache(requestId,scope,getDefaultCacheValue);const[clientResult]=useCachedEffect(requestId,handler,{skip,onResultChanged,retainResultOnChange,scope,fetchPolicy:FetchPolicy.CacheBeforeNetwork});return serverResult??clientResult};
|
|
67
67
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "15.0.
|
|
6
|
+
"version": "15.0.3",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@khanacademy/wonder-stuff-testing": "^4.0.3",
|
|
31
31
|
"@khanacademy/wb-dev-build-settings": "3.3.0",
|
|
32
|
-
"@khanacademy/wonder-blocks-testing-core": "5.
|
|
32
|
+
"@khanacademy/wonder-blocks-testing-core": "5.1.1"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"test": "echo \"Error: no test specified\" && exit 1"
|