@khanacademy/wonder-blocks-data 11.0.16 → 13.0.0

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/components/data.d.ts +2 -2
  3. package/dist/es/index.js +24 -18
  4. package/dist/hooks/use-gql.d.ts +5 -1
  5. package/dist/hooks/use-hydratable-effect.d.ts +6 -6
  6. package/dist/index.js +24 -18
  7. package/dist/util/status.d.ts +4 -3
  8. package/dist/util/types.d.ts +8 -6
  9. package/package.json +3 -3
  10. package/src/components/__tests__/data.test.tsx +6 -13
  11. package/src/components/data.ts +2 -4
  12. package/src/hooks/__tests__/use-cached-effect.test.tsx +79 -40
  13. package/src/hooks/__tests__/use-gql-router-context.test.tsx +1 -2
  14. package/src/hooks/__tests__/use-hydratable-effect.test.ts +1 -2
  15. package/src/hooks/__tests__/use-request-interception.test.tsx +2 -5
  16. package/src/hooks/__tests__/use-server-effect.test.ts +3 -6
  17. package/src/hooks/__tests__/use-shared-cache.test.ts +17 -13
  18. package/src/hooks/use-cached-effect.ts +24 -20
  19. package/src/hooks/use-gql.ts +12 -9
  20. package/src/hooks/use-hydratable-effect.ts +6 -7
  21. package/src/hooks/use-request-interception.ts +13 -11
  22. package/src/hooks/use-shared-cache.ts +4 -2
  23. package/src/util/__tests__/request-api.test.ts +2 -1
  24. package/src/util/__tests__/request-tracking.test.tsx +5 -9
  25. package/src/util/__tests__/result-from-cache-response.test.ts +2 -2
  26. package/src/util/__tests__/serializable-in-memory-cache.test.ts +1 -2
  27. package/src/util/__tests__/ssr-cache.test.ts +2 -4
  28. package/src/util/__tests__/to-gql-operation.test.ts +2 -4
  29. package/src/util/graphql-document-node-parser.ts +6 -6
  30. package/src/util/merge-gql-context.ts +2 -1
  31. package/src/util/request-tracking.ts +6 -2
  32. package/src/util/ssr-cache.ts +11 -8
  33. package/src/util/status.ts +6 -0
  34. package/src/util/types.ts +9 -7
  35. package/tsconfig-build.tsbuildinfo +1 -1
  36. package/dist/components/data.js.flow +0 -63
  37. package/dist/components/gql-router.js.flow +0 -33
  38. package/dist/components/intercept-context.js.flow +0 -18
  39. package/dist/components/intercept-requests.js.flow +0 -51
  40. package/dist/components/track-data.js.flow +0 -16
  41. package/dist/hooks/use-cached-effect.js.flow +0 -83
  42. package/dist/hooks/use-gql-router-context.js.flow +0 -14
  43. package/dist/hooks/use-gql.js.flow +0 -28
  44. package/dist/hooks/use-hydratable-effect.js.flow +0 -122
  45. package/dist/hooks/use-request-interception.js.flow +0 -24
  46. package/dist/hooks/use-server-effect.js.flow +0 -49
  47. package/dist/hooks/use-shared-cache.js.flow +0 -42
  48. package/dist/index.js.flow +0 -47
  49. package/dist/util/data-error.js.flow +0 -62
  50. package/dist/util/get-gql-data-from-response.js.flow +0 -12
  51. package/dist/util/get-gql-request-id.js.flow +0 -16
  52. package/dist/util/gql-error.js.flow +0 -41
  53. package/dist/util/gql-router-context.js.flow +0 -10
  54. package/dist/util/gql-types.js.flow +0 -50
  55. package/dist/util/graphql-document-node-parser.js.flow +0 -29
  56. package/dist/util/graphql-types.js.flow +0 -30
  57. package/dist/util/hydration-cache-api.js.flow +0 -29
  58. package/dist/util/merge-gql-context.js.flow +0 -18
  59. package/dist/util/purge-caches.js.flow +0 -14
  60. package/dist/util/request-api.js.flow +0 -33
  61. package/dist/util/request-fulfillment.js.flow +0 -48
  62. package/dist/util/request-tracking.js.flow +0 -81
  63. package/dist/util/result-from-cache-response.js.flow +0 -14
  64. package/dist/util/scoped-in-memory-cache.js.flow +0 -56
  65. package/dist/util/serializable-in-memory-cache.js.flow +0 -25
  66. package/dist/util/ssr-cache.js.flow +0 -86
  67. package/dist/util/status.js.flow +0 -17
  68. package/dist/util/to-gql-operation.js.flow +0 -41
  69. package/dist/util/types.js.flow +0 -142
  70. package/src/util/graphql-types.js.flow +0 -30
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @khanacademy/wonder-blocks-data
2
2
 
3
+ ## 13.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 65c02cff: Return new no-data state from useCachedEffect when it is not loading and there is no data to return
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [1920feb8]
12
+ - @khanacademy/wonder-blocks-core@6.0.1
13
+
14
+ ## 12.0.0
15
+
16
+ ### Major Changes
17
+
18
+ - 674a1e5c: POJOs have been replace with TS enums
19
+
20
+ ### Patch Changes
21
+
22
+ - 674a1e5c: We're no longer building flow types
23
+ - Updated dependencies [674a1e5c]
24
+ - Updated dependencies [674a1e5c]
25
+ - @khanacademy/wonder-blocks-core@6.0.0
26
+
3
27
  ## 11.0.16
4
28
 
5
29
  ### Patch Changes
@@ -41,12 +41,12 @@ TData extends ValidCacheData> = {
41
41
  * loading state and data or error that gets retrieved from cache or loaded
42
42
  * via the request if no cached value is available.
43
43
  */
44
- children: (result: Result<TData>) => React.ReactNode;
44
+ children: (result: Result<TData>) => React.ReactElement | null;
45
45
  };
46
46
  /**
47
47
  * This component is the main component of Wonder Blocks Data. With this, data
48
48
  * requirements can be placed in a React application in a manner that will
49
49
  * support server-side rendering and efficient caching.
50
50
  */
51
- declare const Data: <TData extends ValidCacheData>({ requestId, handler, children, retainResultOnChange, clientBehavior, }: Props<TData>) => React.ReactElement;
51
+ declare const Data: <TData extends ValidCacheData>({ requestId, handler, children, retainResultOnChange, clientBehavior, }: Props<TData>) => React.ReactElement | null;
52
52
  export default Data;
package/dist/es/index.js CHANGED
@@ -3,12 +3,13 @@ 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';
5
5
 
6
- const FetchPolicy = {
7
- CacheBeforeNetwork: "CacheBeforeNetwork",
8
- CacheAndNetwork: "CacheAndNetwork",
9
- CacheOnly: "CacheOnly",
10
- NetworkOnly: "NetworkOnly"
11
- };
6
+ let FetchPolicy = function (FetchPolicy) {
7
+ FetchPolicy["CacheBeforeNetwork"] = "CacheBeforeNetwork";
8
+ FetchPolicy["CacheAndNetwork"] = "CacheAndNetwork";
9
+ FetchPolicy["CacheOnly"] = "CacheOnly";
10
+ FetchPolicy["NetworkOnly"] = "NetworkOnly";
11
+ return FetchPolicy;
12
+ }({});
12
13
 
13
14
  const DataErrors = Object.freeze({
14
15
  Unknown: "Unknown",
@@ -161,9 +162,9 @@ class SsrCache {
161
162
  this._ssrOnlyCache.purgeAll(realPredicate);
162
163
  };
163
164
  this.cloneHydratableData = () => {
164
- var _cache$DefaultScope;
165
+ var _ref;
165
166
  const cache = this._hydrationCache.clone();
166
- return (_cache$DefaultScope = cache[DefaultScope$2]) != null ? _cache$DefaultScope : {};
167
+ return (_ref = cache[DefaultScope$2]) != null ? _ref : {};
167
168
  };
168
169
  this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
169
170
  this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
@@ -260,7 +261,7 @@ class RequestTracker {
260
261
  }
261
262
  return _default;
262
263
  }
263
- constructor(responseCache = undefined) {
264
+ constructor(responseCache) {
264
265
  this._trackedRequests = {};
265
266
  this._responseCache = void 0;
266
267
  this._requestFulfillment = void 0;
@@ -378,11 +379,15 @@ class TrackData extends React.Component {
378
379
  const loadingStatus = Object.freeze({
379
380
  status: "loading"
380
381
  });
382
+ const noDataStatus = Object.freeze({
383
+ status: "no-data"
384
+ });
381
385
  const abortedStatus = Object.freeze({
382
386
  status: "aborted"
383
387
  });
384
388
  const Status = Object.freeze({
385
389
  loading: () => loadingStatus,
390
+ noData: () => noDataStatus,
386
391
  aborted: () => abortedStatus,
387
392
  success: data => ({
388
393
  status: "success",
@@ -526,19 +531,20 @@ const useCachedEffect = (requestId, handler, options = {}) => {
526
531
  currentRequestRef.current = null;
527
532
  };
528
533
  }, [shouldFetch, fetchRequest]);
529
- const lastResultAgnosticOfIdRef = React.useRef(Status.loading());
530
- const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : Status.loading();
534
+ const lastResultAgnosticOfIdRef = React.useRef(Status.noData());
535
+ const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : shouldFetch ? Status.loading() : Status.noData();
531
536
  const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
532
537
  lastResultAgnosticOfIdRef.current = result;
533
538
  return [result, fetchRequest];
534
539
  };
535
540
 
536
- const WhenClientSide = {
537
- DoNotHydrate: "DoNotHydrate",
538
- ExecuteWhenNoResult: "ExecuteWhenNoResult",
539
- ExecuteWhenNoSuccessResult: "ExecuteWhenNoSuccessResult",
540
- AlwaysExecute: "AlwaysExecute"
541
- };
541
+ let WhenClientSide = function (WhenClientSide) {
542
+ WhenClientSide["DoNotHydrate"] = "DoNotHydrate";
543
+ WhenClientSide["ExecuteWhenNoResult"] = "ExecuteWhenNoResult";
544
+ WhenClientSide["ExecuteWhenNoSuccessResult"] = "ExecuteWhenNoSuccessResult";
545
+ WhenClientSide["AlwaysExecute"] = "AlwaysExecute";
546
+ return WhenClientSide;
547
+ }({});
542
548
  const DefaultScope = "useHydratableEffect";
543
549
  const useHydratableEffect = (requestId, handler, options = {}) => {
544
550
  const {
@@ -839,7 +845,7 @@ const useGql = (context = {}) => {
839
845
  context = {}
840
846
  } = options;
841
847
  const finalContext = mergeGqlContext(defaultContext, context);
842
- return fetch(operation, variables, finalContext).then(getGqlDataFromResponse);
848
+ return fetch(operation, variables, finalContext).then(response => getGqlDataFromResponse(response));
843
849
  }, [gqlRouterContext]);
844
850
  return gqlFetch;
845
851
  };
@@ -1,4 +1,7 @@
1
1
  import type { GqlContext, GqlOperation, GqlFetchOptions } from "../util/gql-types";
2
+ interface GqlFetchFn<TContext extends GqlContext> {
3
+ <TData, TVariables extends Record<any, any>>(operation: GqlOperation<TData, TVariables>, options?: GqlFetchOptions<TVariables, TContext>): Promise<TData>;
4
+ }
2
5
  /**
3
6
  * Hook to obtain a gqlFetch function for performing GraphQL requests.
4
7
  *
@@ -9,4 +12,5 @@ import type { GqlContext, GqlOperation, GqlFetchOptions } from "../util/gql-type
9
12
  * Values in the partial context given to the returned fetch function will
10
13
  * only be included if they have a value other than undefined.
11
14
  */
12
- export declare const useGql: <TContext extends GqlContext>(context?: Partial<TContext>) => <TData, TVariables extends Record<any, any>>(operation: GqlOperation<TData, TVariables>, options?: GqlFetchOptions<TVariables, TContext> | undefined) => Promise<TData>;
15
+ export declare const useGql: <TContext extends GqlContext>(context?: Partial<TContext>) => GqlFetchFn<TContext>;
16
+ export {};
@@ -2,7 +2,7 @@ import type { Result, ValidCacheData } from "../util/types";
2
2
  /**
3
3
  * Policies to define how a hydratable effect should behave client-side.
4
4
  */
5
- export declare const WhenClientSide: {
5
+ export declare enum WhenClientSide {
6
6
  /**
7
7
  * The result from executing the effect server-side will not be hydrated.
8
8
  * The effect will always be executed client-side.
@@ -11,14 +11,14 @@ export declare const WhenClientSide: {
11
11
  * for properly hydrating this component (for example, the action invokes
12
12
  * Apollo which manages its own cache to ensure things render properly).
13
13
  */
14
- readonly DoNotHydrate: "DoNotHydrate";
14
+ DoNotHydrate = "DoNotHydrate",
15
15
  /**
16
16
  * The result from executing the effect server-side will be hydrated.
17
17
  * The effect will only execute client-side if there was no result to
18
18
  * be hydrated (i.e. both error and success hydration results prevent the
19
19
  * effect running client-side).
20
20
  */
21
- readonly ExecuteWhenNoResult: "ExecuteWhenNoResult";
21
+ ExecuteWhenNoResult = "ExecuteWhenNoResult",
22
22
  /**
23
23
  * The result from executing the effect server-side will be hydrated.
24
24
  * If the hydrated result is a success result, the effect will not be
@@ -26,14 +26,14 @@ export declare const WhenClientSide: {
26
26
  * If the hydrated result was not a success result, or there was no
27
27
  * hydrated result, the effect will not be executed.
28
28
  */
29
- readonly ExecuteWhenNoSuccessResult: "ExecuteWhenNoSuccessResult";
29
+ ExecuteWhenNoSuccessResult = "ExecuteWhenNoSuccessResult",
30
30
  /**
31
31
  * The result from executing the effect server-side will be hydrated.
32
32
  * The effect will always be executed client-side, regardless of the
33
33
  * hydrated result status.
34
34
  */
35
- readonly AlwaysExecute: "AlwaysExecute";
36
- };
35
+ AlwaysExecute = "AlwaysExecute"
36
+ }
37
37
  type HydratableEffectOptions<TData extends ValidCacheData> = {
38
38
  /**
39
39
  * How the hook should behave when rendering client-side for the first time.
package/dist/index.js CHANGED
@@ -26,12 +26,13 @@ function _interopNamespace(e) {
26
26
 
27
27
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
28
 
29
- const FetchPolicy = {
30
- CacheBeforeNetwork: "CacheBeforeNetwork",
31
- CacheAndNetwork: "CacheAndNetwork",
32
- CacheOnly: "CacheOnly",
33
- NetworkOnly: "NetworkOnly"
34
- };
29
+ let FetchPolicy = function (FetchPolicy) {
30
+ FetchPolicy["CacheBeforeNetwork"] = "CacheBeforeNetwork";
31
+ FetchPolicy["CacheAndNetwork"] = "CacheAndNetwork";
32
+ FetchPolicy["CacheOnly"] = "CacheOnly";
33
+ FetchPolicy["NetworkOnly"] = "NetworkOnly";
34
+ return FetchPolicy;
35
+ }({});
35
36
 
36
37
  const DataErrors = Object.freeze({
37
38
  Unknown: "Unknown",
@@ -184,9 +185,9 @@ class SsrCache {
184
185
  this._ssrOnlyCache.purgeAll(realPredicate);
185
186
  };
186
187
  this.cloneHydratableData = () => {
187
- var _cache$DefaultScope;
188
+ var _ref;
188
189
  const cache = this._hydrationCache.clone();
189
- return (_cache$DefaultScope = cache[DefaultScope$2]) != null ? _cache$DefaultScope : {};
190
+ return (_ref = cache[DefaultScope$2]) != null ? _ref : {};
190
191
  };
191
192
  this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
192
193
  this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
@@ -283,7 +284,7 @@ class RequestTracker {
283
284
  }
284
285
  return _default;
285
286
  }
286
- constructor(responseCache = undefined) {
287
+ constructor(responseCache) {
287
288
  this._trackedRequests = {};
288
289
  this._responseCache = void 0;
289
290
  this._requestFulfillment = void 0;
@@ -401,11 +402,15 @@ class TrackData extends React__namespace.Component {
401
402
  const loadingStatus = Object.freeze({
402
403
  status: "loading"
403
404
  });
405
+ const noDataStatus = Object.freeze({
406
+ status: "no-data"
407
+ });
404
408
  const abortedStatus = Object.freeze({
405
409
  status: "aborted"
406
410
  });
407
411
  const Status = Object.freeze({
408
412
  loading: () => loadingStatus,
413
+ noData: () => noDataStatus,
409
414
  aborted: () => abortedStatus,
410
415
  success: data => ({
411
416
  status: "success",
@@ -549,19 +554,20 @@ const useCachedEffect = (requestId, handler, options = {}) => {
549
554
  currentRequestRef.current = null;
550
555
  };
551
556
  }, [shouldFetch, fetchRequest]);
552
- const lastResultAgnosticOfIdRef = React__namespace.useRef(Status.loading());
553
- const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : Status.loading();
557
+ const lastResultAgnosticOfIdRef = React__namespace.useRef(Status.noData());
558
+ const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : shouldFetch ? Status.loading() : Status.noData();
554
559
  const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
555
560
  lastResultAgnosticOfIdRef.current = result;
556
561
  return [result, fetchRequest];
557
562
  };
558
563
 
559
- const WhenClientSide = {
560
- DoNotHydrate: "DoNotHydrate",
561
- ExecuteWhenNoResult: "ExecuteWhenNoResult",
562
- ExecuteWhenNoSuccessResult: "ExecuteWhenNoSuccessResult",
563
- AlwaysExecute: "AlwaysExecute"
564
- };
564
+ let WhenClientSide = function (WhenClientSide) {
565
+ WhenClientSide["DoNotHydrate"] = "DoNotHydrate";
566
+ WhenClientSide["ExecuteWhenNoResult"] = "ExecuteWhenNoResult";
567
+ WhenClientSide["ExecuteWhenNoSuccessResult"] = "ExecuteWhenNoSuccessResult";
568
+ WhenClientSide["AlwaysExecute"] = "AlwaysExecute";
569
+ return WhenClientSide;
570
+ }({});
565
571
  const DefaultScope = "useHydratableEffect";
566
572
  const useHydratableEffect = (requestId, handler, options = {}) => {
567
573
  const {
@@ -862,7 +868,7 @@ const useGql = (context = {}) => {
862
868
  context = {}
863
869
  } = options;
864
870
  const finalContext = mergeGqlContext(defaultContext, context);
865
- return fetch(operation, variables, finalContext).then(getGqlDataFromResponse);
871
+ return fetch(operation, variables, finalContext).then(response => getGqlDataFromResponse(response));
866
872
  }, [gqlRouterContext]);
867
873
  return gqlFetch;
868
874
  };
@@ -4,7 +4,8 @@ import type { Result, ValidCacheData } from "./types";
4
4
  */
5
5
  export declare const Status: Readonly<{
6
6
  loading: <TData extends ValidCacheData = ValidCacheData>() => Result<TData>;
7
- aborted: <TData_1 extends ValidCacheData = ValidCacheData>() => Result<TData_1>;
8
- success: <TData_2 extends ValidCacheData>(data: TData_2) => Result<TData_2>;
9
- error: <TData_3 extends ValidCacheData = ValidCacheData>(error: Error) => Result<TData_3>;
7
+ noData: <TData_1 extends ValidCacheData = ValidCacheData>() => Result<TData_1>;
8
+ aborted: <TData_2 extends ValidCacheData = ValidCacheData>() => Result<TData_2>;
9
+ success: <TData_3 extends ValidCacheData>(data: TData_3) => Result<TData_3>;
10
+ error: <TData_4 extends ValidCacheData = ValidCacheData>(error: Error) => Result<TData_4>;
10
11
  }>;
@@ -2,26 +2,26 @@ import type { Metadata } from "@khanacademy/wonder-stuff-core";
2
2
  /**
3
3
  * Defines the various fetch policies that can be applied to requests.
4
4
  */
5
- export declare const FetchPolicy: {
5
+ export declare enum FetchPolicy {
6
6
  /**
7
7
  * If the data is in the cache, return that; otherwise, fetch from the
8
8
  * server.
9
9
  */
10
- readonly CacheBeforeNetwork: "CacheBeforeNetwork";
10
+ CacheBeforeNetwork = "CacheBeforeNetwork",
11
11
  /**
12
12
  * If the data is in the cache, return that; always fetch from the server
13
13
  * regardless of cache.
14
14
  */
15
- readonly CacheAndNetwork: "CacheAndNetwork";
15
+ CacheAndNetwork = "CacheAndNetwork",
16
16
  /**
17
17
  * If the data is in the cache, return that; otherwise, do nothing.
18
18
  */
19
- readonly CacheOnly: "CacheOnly";
19
+ CacheOnly = "CacheOnly",
20
20
  /**
21
21
  * Ignore any existing cached result; always fetch from the server.
22
22
  */
23
- readonly NetworkOnly: "NetworkOnly";
24
- };
23
+ NetworkOnly = "NetworkOnly"
24
+ }
25
25
  /**
26
26
  * Define what can be cached.
27
27
  *
@@ -34,6 +34,8 @@ export type ValidCacheData = string | boolean | number | Record<any, any> | Arra
34
34
  */
35
35
  export type Result<TData extends ValidCacheData> = {
36
36
  status: "loading";
37
+ } | {
38
+ status: "no-data";
37
39
  } | {
38
40
  status: "success";
39
41
  data: TData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-data",
3
- "version": "11.0.16",
3
+ "version": "13.0.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,14 +14,14 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@babel/runtime": "^7.18.6",
17
- "@khanacademy/wonder-blocks-core": "^5.4.0"
17
+ "@khanacademy/wonder-blocks-core": "^6.0.1"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "@khanacademy/wonder-stuff-core": "^1.2.2",
21
21
  "react": "16.14.0"
22
22
  },
23
23
  "devDependencies": {
24
- "wb-dev-build-settings": "^0.9.7"
24
+ "@khanacademy/wb-dev-build-settings": "^1.0.0"
25
25
  },
26
26
  "author": "",
27
27
  "license": "MIT"
@@ -47,7 +47,7 @@ describe("Data", () => {
47
47
 
48
48
  it("should make request for data on construction", async () => {
49
49
  // Arrange
50
- const response = Promise.resolve("data");
50
+ const response: any = Promise.resolve("data");
51
51
  const fakeHandler = jest.fn().mockReturnValue(response);
52
52
  const fakeChildrenFn = jest.fn(() => null);
53
53
 
@@ -57,7 +57,6 @@ describe("Data", () => {
57
57
  {fakeChildrenFn}
58
58
  </Data>,
59
59
  );
60
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
61
60
  await act(() => response);
62
61
 
63
62
  // Assert
@@ -66,7 +65,7 @@ describe("Data", () => {
66
65
 
67
66
  it("should initially render children with loading", async () => {
68
67
  // Arrange
69
- const response = Promise.resolve("data");
68
+ const response: any = Promise.resolve("data");
70
69
  const fakeHandler = jest.fn().mockReturnValue(response);
71
70
  const fakeChildrenFn = jest.fn(() => null);
72
71
 
@@ -76,7 +75,6 @@ describe("Data", () => {
76
75
  {fakeChildrenFn}
77
76
  </Data>,
78
77
  );
79
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
80
78
  await act(() => response);
81
79
 
82
80
  // Assert
@@ -272,7 +270,7 @@ describe("Data", () => {
272
270
 
273
271
  it("should ignore resolution of pending handler fulfillment when id changes", async () => {
274
272
  // Arrange
275
- const oldRequest = Promise.resolve("OLD DATA");
273
+ const oldRequest: any = Promise.resolve("OLD DATA");
276
274
  const oldHandler = jest
277
275
  .fn()
278
276
  .mockReturnValueOnce(oldRequest)
@@ -294,7 +292,6 @@ describe("Data", () => {
294
292
  {fakeChildrenFn}
295
293
  </Data>,
296
294
  );
297
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
298
295
  await act(() => oldRequest);
299
296
 
300
297
  // Assert
@@ -343,14 +340,13 @@ describe("Data", () => {
343
340
 
344
341
  it("should ignore catastrophic request fulfillment when id changes", async () => {
345
342
  // Arrange
346
- const catastrophe = Promise.resolve({
343
+ const catastrophe: any = Promise.resolve({
347
344
  status: "error",
348
345
  error: new Error("CATASTROPHE!"),
349
346
  });
350
347
  jest.spyOn(
351
348
  RequestFulfillment.Default,
352
349
  "fulfill",
353
- // @ts-expect-error [FEI-5019] - TS2345 - Argument of type 'Promise<{ status: string; error: Error; }>' is not assignable to parameter of type 'Promise<Result<ValidCacheData>>'.
354
350
  ).mockReturnValueOnce(catastrophe);
355
351
  const oldHandler = jest.fn().mockResolvedValue("OLD DATA");
356
352
 
@@ -367,7 +363,6 @@ describe("Data", () => {
367
363
  </Data>,
368
364
  );
369
365
  await act(() =>
370
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
371
366
  catastrophe.catch(() => {
372
367
  /* ignore */
373
368
  }),
@@ -428,8 +423,8 @@ describe("Data", () => {
428
423
 
429
424
  it("should retain old data while reloading if retainResultOnChange is true", async () => {
430
425
  // Arrange
431
- const response1 = Promise.resolve("data1");
432
- const response2 = Promise.resolve("data2");
426
+ const response1: any = Promise.resolve("data1");
427
+ const response2: any = Promise.resolve("data2");
433
428
  const fakeHandler1 = () => response1;
434
429
  const fakeHandler2 = () => response2;
435
430
  const fakeChildrenFn = jest.fn(() => null);
@@ -445,7 +440,6 @@ describe("Data", () => {
445
440
  </Data>,
446
441
  );
447
442
  fakeChildrenFn.mockClear();
448
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
449
443
  await act(() => response1);
450
444
  wrapper.rerender(
451
445
  <Data
@@ -456,7 +450,6 @@ describe("Data", () => {
456
450
  {fakeChildrenFn}
457
451
  </Data>,
458
452
  );
459
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
460
453
  await act(() => response2);
461
454
 
462
455
  // Assert
@@ -48,7 +48,7 @@ type Props<
48
48
  * loading state and data or error that gets retrieved from cache or loaded
49
49
  * via the request if no cached value is available.
50
50
  */
51
- children: (result: Result<TData>) => React.ReactNode;
51
+ children: (result: Result<TData>) => React.ReactElement | null;
52
52
  };
53
53
 
54
54
  /**
@@ -62,13 +62,11 @@ const Data = <TData extends ValidCacheData>({
62
62
  children,
63
63
  retainResultOnChange = false,
64
64
  clientBehavior = WhenClientSide.ExecuteWhenNoSuccessResult,
65
- }: Props<TData>): React.ReactElement => {
65
+ }: Props<TData>): React.ReactElement | null => {
66
66
  const result = useHydratableEffect(requestId, handler, {
67
67
  retainResultOnChange,
68
68
  clientBehavior,
69
69
  });
70
- // @ts-expect-error: React TS types don't allow functional components to return
71
- // ReactNodes even though React itself does.
72
70
  return children(result);
73
71
  };
74
72