@depup/reduxjs__toolkit 2.12.0-depup.28 → 2.13.0-depup.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 (93) hide show
  1. package/README.md +4 -4
  2. package/changes.json +3 -3
  3. package/dist/cjs/redux-toolkit.development.cjs +1755 -2247
  4. package/dist/cjs/redux-toolkit.development.cjs.map +1 -1
  5. package/dist/cjs/redux-toolkit.production.min.cjs +1 -2
  6. package/dist/cjs/redux-toolkit.production.min.cjs.map +1 -1
  7. package/dist/index.d.mts +1496 -1525
  8. package/dist/index.d.ts +1496 -1525
  9. package/dist/query/cjs/rtk-query.development.cjs +2059 -2990
  10. package/dist/query/cjs/rtk-query.development.cjs.map +1 -1
  11. package/dist/query/cjs/rtk-query.production.min.cjs +1 -1
  12. package/dist/query/cjs/rtk-query.production.min.cjs.map +1 -1
  13. package/dist/query/index.d.mts +2300 -2308
  14. package/dist/query/index.d.ts +2300 -2308
  15. package/dist/query/react/cjs/rtk-query-react.development.cjs +609 -714
  16. package/dist/query/react/cjs/rtk-query-react.development.cjs.map +1 -1
  17. package/dist/query/react/cjs/rtk-query-react.production.min.cjs +1 -1
  18. package/dist/query/react/cjs/rtk-query-react.production.min.cjs.map +1 -1
  19. package/dist/query/react/index.d.mts +516 -523
  20. package/dist/query/react/index.d.ts +516 -523
  21. package/dist/query/react/rtk-query-react.browser.mjs +1 -1
  22. package/dist/query/react/rtk-query-react.browser.mjs.map +1 -1
  23. package/dist/query/react/rtk-query-react.legacy-esm.js +672 -714
  24. package/dist/query/react/rtk-query-react.legacy-esm.js.map +1 -1
  25. package/dist/query/react/rtk-query-react.modern.mjs +586 -679
  26. package/dist/query/react/rtk-query-react.modern.mjs.map +1 -1
  27. package/dist/query/rtk-query.browser.mjs +1 -1
  28. package/dist/query/rtk-query.browser.mjs.map +1 -1
  29. package/dist/query/rtk-query.legacy-esm.js +2175 -3014
  30. package/dist/query/rtk-query.legacy-esm.js.map +1 -1
  31. package/dist/query/rtk-query.modern.mjs +2052 -2949
  32. package/dist/query/rtk-query.modern.mjs.map +1 -1
  33. package/dist/react/cjs/redux-toolkit-react.development.cjs +30 -51
  34. package/dist/react/cjs/redux-toolkit-react.development.cjs.map +1 -1
  35. package/dist/react/cjs/redux-toolkit-react.production.min.cjs +1 -1
  36. package/dist/react/cjs/redux-toolkit-react.production.min.cjs.map +1 -1
  37. package/dist/react/index.d.mts +12 -15
  38. package/dist/react/index.d.ts +12 -15
  39. package/dist/react/redux-toolkit-react.browser.mjs +1 -1
  40. package/dist/react/redux-toolkit-react.browser.mjs.map +1 -1
  41. package/dist/react/redux-toolkit-react.legacy-esm.js +83 -44
  42. package/dist/react/redux-toolkit-react.legacy-esm.js.map +1 -1
  43. package/dist/react/redux-toolkit-react.modern.mjs +23 -25
  44. package/dist/react/redux-toolkit-react.modern.mjs.map +1 -1
  45. package/dist/redux-toolkit.browser.mjs +1 -2
  46. package/dist/redux-toolkit.browser.mjs.map +1 -1
  47. package/dist/redux-toolkit.legacy-esm.js +1748 -2201
  48. package/dist/redux-toolkit.legacy-esm.js.map +1 -1
  49. package/dist/redux-toolkit.modern.mjs +1670 -2171
  50. package/dist/redux-toolkit.modern.mjs.map +1 -1
  51. package/package.json +17 -33
  52. package/skills/build-modern-redux-apps/modern-redux/SKILL.md +23 -14
  53. package/skills/build-modern-redux-apps/modern-redux/references/store-lifetime.md +6 -6
  54. package/skills/build-modern-redux-apps/redux-dataflow/SKILL.md +13 -10
  55. package/skills/evolve-and-diagnose-redux-apps/debug-redux-toolkit-apps/SKILL.md +6 -6
  56. package/skills/evolve-and-diagnose-redux-apps/migrate-to-modern-redux/SKILL.md +7 -8
  57. package/skills/manage-server-data/adopt-rtk-query/SKILL.md +13 -11
  58. package/skills/model-redux-state/build-slices-and-selectors/SKILL.md +26 -14
  59. package/skills/model-redux-state/design-state-ownership/SKILL.md +11 -12
  60. package/skills/model-redux-state/design-state-ownership/references/state-ownership.md +6 -6
  61. package/skills/orchestrate-side-effects/handle-side-effects/SKILL.md +27 -23
  62. package/skills/orchestrate-side-effects/handle-side-effects/references/listener-workflows.md +4 -4
  63. package/src/autoBatchEnhancer.ts +5 -3
  64. package/src/combineSlices.ts +5 -5
  65. package/src/createAction.ts +11 -6
  66. package/src/createAsyncThunk.ts +14 -2
  67. package/src/createReducer.ts +1 -1
  68. package/src/createSlice.ts +9 -4
  69. package/src/dynamicMiddleware/index.ts +21 -5
  70. package/src/entities/models.ts +2 -1
  71. package/src/entities/sorted_state_adapter.ts +35 -24
  72. package/src/entities/unsorted_state_adapter.ts +1 -1
  73. package/src/immutableStateInvariantMiddleware.ts +34 -5
  74. package/src/listenerMiddleware/types.ts +10 -10
  75. package/src/mapBuilders.ts +2 -5
  76. package/src/matchers.ts +7 -1
  77. package/src/query/core/apiState.ts +1 -1
  78. package/src/query/core/buildInitiate.ts +19 -15
  79. package/src/query/core/buildMiddleware/cacheLifecycle.ts +3 -1
  80. package/src/query/core/buildMiddleware/index.ts +1 -1
  81. package/src/query/core/buildMiddleware/invalidationByTags.ts +4 -1
  82. package/src/query/core/buildMiddleware/polling.ts +12 -3
  83. package/src/query/core/buildMiddleware/types.ts +5 -2
  84. package/src/query/core/buildSlice.ts +2 -2
  85. package/src/query/core/buildThunks.ts +19 -0
  86. package/src/query/core/module.ts +9 -3
  87. package/src/query/createApi.ts +4 -1
  88. package/src/query/endpointDefinitions.ts +15 -9
  89. package/src/query/fetchBaseQuery.ts +1 -1
  90. package/src/query/react/buildHooks.ts +54 -51
  91. package/src/query/react/namedHooks.ts +28 -24
  92. package/src/query/utils/isAbsoluteUrl.ts +8 -3
  93. package/src/serializableStateInvariantMiddleware.ts +1 -1
@@ -86,8 +86,11 @@ export type SubMiddlewareApi = MiddlewareAPI<
86
86
  RootState<EndpointDefinitions, string, string>
87
87
  >
88
88
 
89
- export interface BuildSubMiddlewareInput
90
- extends BuildMiddlewareInput<EndpointDefinitions, string, string> {
89
+ export interface BuildSubMiddlewareInput extends BuildMiddlewareInput<
90
+ EndpointDefinitions,
91
+ string,
92
+ string
93
+ > {
91
94
  internalState: InternalMiddlewareState
92
95
  refetchQuery(
93
96
  querySubState: Exclude<
@@ -512,7 +512,7 @@ export function buildSlice({
512
512
 
513
513
  for (const { type, id } of providedTags) {
514
514
  const subscribedQueries = ((draft.tags[type] ??= {})[
515
- id || '__internal_without_id'
515
+ id ?? '__internal_without_id'
516
516
  ] ??= [])
517
517
  const alreadySubscribed =
518
518
  subscribedQueries.includes(queryCacheKey)
@@ -549,7 +549,7 @@ export function buildSlice({
549
549
  )) {
550
550
  for (const [id, cacheKeys] of Object.entries(incomingTags)) {
551
551
  const subscribedQueries = ((draft.tags[type] ??= {})[
552
- id || '__internal_without_id'
552
+ id ?? '__internal_without_id'
553
553
  ] ??= [])
554
554
  for (const queryCacheKey of cacheKeys) {
555
555
  const alreadySubscribed =
@@ -971,6 +971,25 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".`
971
971
  return false
972
972
  }
973
973
 
974
+ if (direction && isInfiniteQueryDefinition(endpointDefinition)) {
975
+ const cachedData = requestState?.data as
976
+ | InfiniteData<unknown, unknown>
977
+ | undefined
978
+ if (cachedData?.pages.length) {
979
+ const { infiniteQueryOptions } = endpointDefinition
980
+ const pageParamFn =
981
+ direction === 'forward' ? getNextPageParam : getPreviousPageParam
982
+ const nextParam = pageParamFn(
983
+ infiniteQueryOptions,
984
+ cachedData,
985
+ currentArg,
986
+ )
987
+ if (nextParam == null) {
988
+ return false
989
+ }
990
+ }
991
+ }
992
+
974
993
  return true
975
994
  },
976
995
  dispatchConditionRejection: true,
@@ -431,7 +431,9 @@ export interface ApiEndpointQuery<
431
431
  Definition extends QueryDefinition<any, any, any, any, any>,
432
432
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
433
433
  Definitions extends EndpointDefinitions,
434
- > extends BuildThunksApiEndpointQuery<Definition>,
434
+ >
435
+ extends
436
+ BuildThunksApiEndpointQuery<Definition>,
435
437
  BuildInitiateApiEndpointQuery<Definition>,
436
438
  BuildSelectorsApiEndpointQuery<Definition, Definitions> {
437
439
  name: string
@@ -446,7 +448,9 @@ export interface ApiEndpointInfiniteQuery<
446
448
  Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
447
449
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
448
450
  Definitions extends EndpointDefinitions,
449
- > extends BuildThunksApiEndpointInfiniteQuery<Definition>,
451
+ >
452
+ extends
453
+ BuildThunksApiEndpointInfiniteQuery<Definition>,
450
454
  BuildInitiateApiEndpointInfiniteQuery<Definition>,
451
455
  BuildSelectorsApiEndpointInfiniteQuery<Definition, Definitions> {
452
456
  name: string
@@ -462,7 +466,9 @@ export interface ApiEndpointMutation<
462
466
  Definition extends MutationDefinition<any, any, any, any, any>,
463
467
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
464
468
  Definitions extends EndpointDefinitions,
465
- > extends BuildThunksApiEndpointMutation<Definition>,
469
+ >
470
+ extends
471
+ BuildThunksApiEndpointMutation<Definition>,
466
472
  BuildInitiateApiEndpointMutation<Definition>,
467
473
  BuildSelectorsApiEndpointMutation<Definition, Definitions> {
468
474
  name: string
@@ -365,7 +365,10 @@ export function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(
365
365
  extractRehydrationInfo,
366
366
  serializeQueryArgs(queryArgsApi) {
367
367
  let finalSerializeQueryArgs = defaultSerializeQueryArgs
368
- if ('serializeQueryArgs' in queryArgsApi.endpointDefinition) {
368
+ if (
369
+ queryArgsApi.endpointDefinition &&
370
+ 'serializeQueryArgs' in queryArgsApi.endpointDefinition
371
+ ) {
369
372
  const endpointSQA =
370
373
  queryArgsApi.endpointDefinition.serializeQueryArgs!
371
374
  finalSerializeQueryArgs = (queryArgsApi) => {
@@ -614,7 +614,9 @@ export interface QueryExtraOptions<
614
614
  BaseQuery extends BaseQueryFn,
615
615
  ReducerPath extends string = string,
616
616
  RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
617
- > extends CacheLifecycleQueryExtraOptions<
617
+ >
618
+ extends
619
+ CacheLifecycleQueryExtraOptions<
618
620
  ResultType,
619
621
  QueryArg,
620
622
  BaseQuery,
@@ -925,7 +927,9 @@ export interface InfiniteQueryExtraOptions<
925
927
  BaseQuery extends BaseQueryFn,
926
928
  ReducerPath extends string = string,
927
929
  RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
928
- > extends CacheLifecycleInfiniteQueryExtraOptions<
930
+ >
931
+ extends
932
+ CacheLifecycleInfiniteQueryExtraOptions<
929
933
  InfiniteData<ResultType, PageParam>,
930
934
  QueryArg,
931
935
  BaseQuery,
@@ -1140,7 +1144,9 @@ export interface MutationExtraOptions<
1140
1144
  BaseQuery extends BaseQueryFn,
1141
1145
  ReducerPath extends string = string,
1142
1146
  RawResultType extends BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1143
- > extends CacheLifecycleMutationExtraOptions<
1147
+ >
1148
+ extends
1149
+ CacheLifecycleMutationExtraOptions<
1144
1150
  ResultType,
1145
1151
  QueryArg,
1146
1152
  BaseQuery,
@@ -1378,8 +1384,8 @@ export type EndpointBuilder<
1378
1384
  query<
1379
1385
  ResultType,
1380
1386
  QueryArg,
1381
- RawResultType extends
1382
- BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1387
+ RawResultType extends BaseQueryResult<BaseQuery> =
1388
+ BaseQueryResult<BaseQuery>,
1383
1389
  >(
1384
1390
  definition: OmitFromUnion<
1385
1391
  QueryDefinition<
@@ -1460,8 +1466,8 @@ export type EndpointBuilder<
1460
1466
  mutation<
1461
1467
  ResultType,
1462
1468
  QueryArg,
1463
- RawResultType extends
1464
- BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1469
+ RawResultType extends BaseQueryResult<BaseQuery> =
1470
+ BaseQueryResult<BaseQuery>,
1465
1471
  >(
1466
1472
  definition: OmitFromUnion<
1467
1473
  MutationDefinition<
@@ -1487,8 +1493,8 @@ export type EndpointBuilder<
1487
1493
  ResultType,
1488
1494
  QueryArg,
1489
1495
  PageParam,
1490
- RawResultType extends
1491
- BaseQueryResult<BaseQuery> = BaseQueryResult<BaseQuery>,
1496
+ RawResultType extends BaseQueryResult<BaseQuery> =
1497
+ BaseQueryResult<BaseQuery>,
1492
1498
  >(
1493
1499
  definition: OmitFromUnion<
1494
1500
  InfiniteQueryDefinition<
@@ -132,7 +132,7 @@ export type FetchBaseQueryArgs = {
132
132
  * in a predicate function for your given api to get the same automatic stringifying behavior
133
133
  * @example
134
134
  * ```ts
135
- * const isJsonContentType = (headers: Headers) => ["application/vnd.api+json", "application/json", "application/vnd.hal+json"].includes(headers.get("content-type")?.trim());
135
+ * const isJsonContentType = (headers: Headers) => ["application/vnd.api+json", "application/json", "application/vnd.hal+json"].includes((headers.get("content-type") ?? "").trim());
136
136
  * ```
137
137
  */
138
138
  isJsonContentType?: (headers: Headers) => boolean
@@ -587,7 +587,7 @@ export type UseQueryStateOptions<
587
587
  *
588
588
  * return (
589
589
  * <ul>
590
- * {posts?.data?.map((post) => (
590
+ * {posts?.map((post) => (
591
591
  * <PostById key={post.id} id={post.id} />
592
592
  * ))}
593
593
  * </ul>
@@ -1171,7 +1171,7 @@ export type UseInfiniteQueryStateOptions<
1171
1171
  *
1172
1172
  * return (
1173
1173
  * <ul>
1174
- * {posts?.data?.map((post) => (
1174
+ * {posts?.map((post) => (
1175
1175
  * <PostById key={post.id} id={post.id} />
1176
1176
  * ))}
1177
1177
  * </ul>
@@ -1286,6 +1286,8 @@ type UseInfiniteQueryStateBaseResult<
1286
1286
  hasPreviousPage: boolean
1287
1287
  isFetchingNextPage: boolean
1288
1288
  isFetchingPreviousPage: boolean
1289
+ isFetchNextPageError: boolean
1290
+ isFetchPreviousPageError: boolean
1289
1291
  }
1290
1292
 
1291
1293
  type UseInfiniteQueryStateDefaultResult<
@@ -1510,7 +1512,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1510
1512
  api,
1511
1513
  moduleOptions: {
1512
1514
  batch,
1513
- hooks: { useDispatch, useSelector, useStore },
1515
+ hooks: { useDispatch, useSelector },
1514
1516
  unstable__sideEffectsInRender,
1515
1517
  createSelector,
1516
1518
  },
@@ -1527,12 +1529,14 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1527
1529
  deps?: DependencyList,
1528
1530
  ) => void = unstable__sideEffectsInRender ? (cb) => cb() : useEffect
1529
1531
 
1530
- type UnsubscribePromiseRef = React.RefObject<
1531
- { unsubscribe?: () => void } | undefined
1532
- >
1532
+ type UnsubscribePromiseRef = {
1533
+ current: { unsubscribe?: () => void } | undefined
1534
+ }
1533
1535
 
1534
- const unsubscribePromiseRef = (ref: UnsubscribePromiseRef) =>
1536
+ const unsubscribePromiseRef = (ref: UnsubscribePromiseRef) => {
1535
1537
  ref.current?.unsubscribe?.()
1538
+ ref.current = undefined
1539
+ }
1536
1540
 
1537
1541
  const endpointDefinitions = context.endpointDefinitions
1538
1542
 
@@ -1570,9 +1574,9 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1570
1574
  lastResult = undefined
1571
1575
  }
1572
1576
 
1573
- // data is the last known good request result we have tracked - or if none has been tracked yet the last good result for the current args
1574
- let data = currentState.isSuccess ? currentState.data : lastResult?.data
1575
- if (data === undefined) data = currentState.data
1577
+ // data is the latest available cache entry, or the last known good request result we have tracked
1578
+ let data = currentState.data
1579
+ if (data === undefined) data = lastResult?.data
1576
1580
 
1577
1581
  const hasData = data !== undefined
1578
1582
 
@@ -1588,10 +1592,14 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1588
1592
  // isSuccess = true when data is present and we're not refetching after an error.
1589
1593
  // That includes cases where the _current_ item is either actively
1590
1594
  // fetching or about to fetch due to an uninitialized entry.
1595
+ // The cache entry keeps `error` set through a pending refetch and only
1596
+ // clears it on success, so the entry itself tells us if this is a
1597
+ // refetch-after-error without consulting `lastResult`.
1591
1598
  const isSuccess =
1592
1599
  currentState.isSuccess ||
1593
1600
  (hasData &&
1594
- ((isFetching && !lastResult?.isError) || currentState.isUninitialized))
1601
+ ((isFetching && currentState.error === undefined) ||
1602
+ currentState.isUninitialized))
1595
1603
 
1596
1604
  return {
1597
1605
  ...currentState,
@@ -1630,9 +1638,9 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1630
1638
  lastResult = undefined
1631
1639
  }
1632
1640
 
1633
- // data is the last known good request result we have tracked - or if none has been tracked yet the last good result for the current args
1634
- let data = currentState.isSuccess ? currentState.data : lastResult?.data
1635
- if (data === undefined) data = currentState.data
1641
+ // data is the latest available cache entry, or the last known good request result we have tracked
1642
+ let data = currentState.data
1643
+ if (data === undefined) data = lastResult?.data
1636
1644
 
1637
1645
  const hasData = data !== undefined
1638
1646
 
@@ -1646,10 +1654,12 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1646
1654
  // isSuccess = true when data is present and we're not refetching after an error.
1647
1655
  // That includes cases where the _current_ item is either actively
1648
1656
  // fetching or about to fetch due to an uninitialized entry.
1657
+ // See `queryStatePreSelector` for why this reads `error` from the entry.
1649
1658
  const isSuccess =
1650
1659
  currentState.isSuccess ||
1651
1660
  (hasData &&
1652
- ((isFetching && !lastResult?.isError) || currentState.isUninitialized))
1661
+ ((isFetching && currentState.error === undefined) ||
1662
+ currentState.isUninitialized))
1653
1663
 
1654
1664
  return {
1655
1665
  ...currentState,
@@ -1703,10 +1713,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1703
1713
  >
1704
1714
  const dispatch = useDispatch<ThunkDispatch<any, any, UnknownAction>>()
1705
1715
 
1706
- // TODO: Change this to `useRef<SubscriptionSelectors>(undefined)` after upgrading to React 19.
1707
- const subscriptionSelectorsRef = useRef<SubscriptionSelectors | undefined>(
1708
- undefined,
1709
- )
1716
+ const subscriptionSelectorsRef = useRef<SubscriptionSelectors>(undefined)
1710
1717
 
1711
1718
  if (!subscriptionSelectorsRef.current) {
1712
1719
  const returnedValue = dispatch(
@@ -1745,10 +1752,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1745
1752
  ).refetchCachedPages
1746
1753
  const stableRefetchCachedPages = useShallowStableValue(refetchCachedPages)
1747
1754
 
1748
- /**
1749
- * @todo Change this to `useRef<QueryActionCreatorResult<any>>(undefined)` after upgrading to React 19.
1750
- */
1751
- const promiseRef = useRef<T | undefined>(undefined)
1755
+ const promiseRef = useRef<T>(undefined)
1752
1756
 
1753
1757
  let { queryCacheKey, requestId } = promiseRef.current || {}
1754
1758
 
@@ -1848,6 +1852,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1848
1852
  type ApiRootState = Parameters<ReturnType<typeof select>>[0]
1849
1853
 
1850
1854
  const lastValue = useRef<any>(undefined)
1855
+ const latestDefaultResult = useRef<any>(undefined)
1851
1856
 
1852
1857
  const selectDefaultResult: Selector<ApiRootState, any, [any]> = useMemo(
1853
1858
  () =>
@@ -1862,6 +1867,11 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1862
1867
  (_: ApiRootState, lastResult: any) => lastResult,
1863
1868
  (_: ApiRootState) => stableArg,
1864
1869
  ],
1870
+ // `preSelector` is a union of the standard/infinite query pre-selectors.
1871
+ // `tsc` attributes the resulting overload error to the `createSelector` call
1872
+ // (suppressed above), but `tsgo` attributes it to this argument line, so it
1873
+ // needs its own directive.
1874
+ // @ts-ignore
1865
1875
  preSelector,
1866
1876
  {
1867
1877
  memoizeOptions: {
@@ -1872,30 +1882,28 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1872
1882
  [select, stableArg],
1873
1883
  )
1874
1884
 
1875
- const querySelector: Selector<ApiRootState, any, [any]> = useMemo(
1876
- () =>
1885
+ const querySelector = useMemo(() => {
1886
+ const selectResult: Selector<ApiRootState, any, [any]> =
1877
1887
  selectFromResult
1878
1888
  ? createSelector([selectDefaultResult], selectFromResult, {
1879
1889
  devModeChecks: { identityFunctionCheck: 'never' },
1880
1890
  })
1881
- : selectDefaultResult,
1882
- [selectDefaultResult, selectFromResult],
1883
- )
1891
+ : selectDefaultResult
1892
+ return (state: RootState<Definitions, any, any>) => {
1893
+ const lastResult = lastValue.current
1894
+ const result = selectResult(state, lastResult)
1895
+ // Same args as the input selector call that just happened, so this
1896
+ // is a memoized read of the un-narrowed result for the next pass.
1897
+ latestDefaultResult.current = selectDefaultResult(state, lastResult)
1898
+ return result
1899
+ }
1900
+ }, [selectDefaultResult, selectFromResult])
1884
1901
 
1885
- const currentState = useSelector(
1886
- (state: RootState<Definitions, any, any>) =>
1887
- querySelector(state, lastValue.current),
1888
- shallowEqual,
1889
- )
1902
+ const currentState = useSelector(querySelector, shallowEqual)
1890
1903
 
1891
- const store = useStore<RootState<Definitions, any, any>>()
1892
- const newLastValue = selectDefaultResult(
1893
- store.getState(),
1894
- lastValue.current,
1895
- )
1896
1904
  useIsomorphicLayoutEffect(() => {
1897
- lastValue.current = newLastValue
1898
- }, [newLastValue])
1905
+ lastValue.current = latestDefaultResult.current
1906
+ })
1899
1907
 
1900
1908
  return currentState
1901
1909
  }
@@ -1909,8 +1917,6 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1909
1917
  useEffect(() => {
1910
1918
  return () => {
1911
1919
  unsubscribePromiseRef(promiseRef)
1912
- // eslint-disable-next-line react-hooks/exhaustive-deps
1913
- ;(promiseRef.current as any) = undefined
1914
1920
  }
1915
1921
  }, [promiseRef])
1916
1922
  }
@@ -1952,7 +1958,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1952
1958
  refetchOnFocus,
1953
1959
  pollingInterval = 0,
1954
1960
  skipPollingIfUnfocused = false,
1955
- } = {}) => {
1961
+ }: SubscriptionOptions = {}) => {
1956
1962
  const { initiate } = api.endpoints[endpointName] as ApiEndpointQuery<
1957
1963
  QueryDefinition<any, any, any, any, any>,
1958
1964
  Definitions
@@ -1961,13 +1967,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
1961
1967
 
1962
1968
  const [arg, setArg] = useState<any>(UNINITIALIZED_VALUE)
1963
1969
 
1964
- // TODO: Change this to `useRef<QueryActionCreatorResult<any>>(undefined)` after upgrading to React 19.
1965
- /**
1966
- * @todo Change this to `useRef<QueryActionCreatorResult<any>>(undefined)` after upgrading to React 19.
1967
- */
1968
- const promiseRef = useRef<QueryActionCreatorResult<any> | undefined>(
1969
- undefined,
1970
- )
1970
+ const promiseRef = useRef<QueryActionCreatorResult<any>>(undefined)
1971
1971
 
1972
1972
  const stableSubscriptionOptions = useShallowStableValue({
1973
1973
  refetchOnReconnect,
@@ -2218,7 +2218,10 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
2218
2218
  }
2219
2219
 
2220
2220
  function buildMutationHook(name: string): UseMutation<any> {
2221
- return ({ selectFromResult, fixedCacheKey } = {}) => {
2221
+ return ({
2222
+ selectFromResult,
2223
+ fixedCacheKey,
2224
+ }: UseMutationStateOptions<any, any> = {}) => {
2222
2225
  const { select, initiate } = api.endpoints[name] as ApiEndpointMutation<
2223
2226
  MutationDefinition<any, any, any, any, any>,
2224
2227
  Definitions
@@ -13,41 +13,45 @@ import type {
13
13
  } from './buildHooks'
14
14
 
15
15
  type QueryHookNames<Definitions extends EndpointDefinitions> = {
16
- [K in keyof Definitions as Definitions[K] extends {
17
- type: DefinitionType.query
18
- }
19
- ? `use${Capitalize<K & string>}Query`
20
- : never]: UseQuery<
21
- Extract<Definitions[K], QueryDefinition<any, any, any, any>>
22
- >
16
+ [
17
+ K in keyof Definitions as Definitions[K] extends {
18
+ type: DefinitionType.query
19
+ }
20
+ ? `use${Capitalize<K & string>}Query`
21
+ : never
22
+ ]: UseQuery<Extract<Definitions[K], QueryDefinition<any, any, any, any>>>
23
23
  }
24
24
 
25
25
  type LazyQueryHookNames<Definitions extends EndpointDefinitions> = {
26
- [K in keyof Definitions as Definitions[K] extends {
27
- type: DefinitionType.query
28
- }
29
- ? `useLazy${Capitalize<K & string>}Query`
30
- : never]: UseLazyQuery<
31
- Extract<Definitions[K], QueryDefinition<any, any, any, any>>
32
- >
26
+ [
27
+ K in keyof Definitions as Definitions[K] extends {
28
+ type: DefinitionType.query
29
+ }
30
+ ? `useLazy${Capitalize<K & string>}Query`
31
+ : never
32
+ ]: UseLazyQuery<Extract<Definitions[K], QueryDefinition<any, any, any, any>>>
33
33
  }
34
34
 
35
35
  type InfiniteQueryHookNames<Definitions extends EndpointDefinitions> = {
36
- [K in keyof Definitions as Definitions[K] extends {
37
- type: DefinitionType.infinitequery
38
- }
39
- ? `use${Capitalize<K & string>}InfiniteQuery`
40
- : never]: UseInfiniteQuery<
36
+ [
37
+ K in keyof Definitions as Definitions[K] extends {
38
+ type: DefinitionType.infinitequery
39
+ }
40
+ ? `use${Capitalize<K & string>}InfiniteQuery`
41
+ : never
42
+ ]: UseInfiniteQuery<
41
43
  Extract<Definitions[K], InfiniteQueryDefinition<any, any, any, any, any>>
42
44
  >
43
45
  }
44
46
 
45
47
  type MutationHookNames<Definitions extends EndpointDefinitions> = {
46
- [K in keyof Definitions as Definitions[K] extends {
47
- type: DefinitionType.mutation
48
- }
49
- ? `use${Capitalize<K & string>}Mutation`
50
- : never]: UseMutation<
48
+ [
49
+ K in keyof Definitions as Definitions[K] extends {
50
+ type: DefinitionType.mutation
51
+ }
52
+ ? `use${Capitalize<K & string>}Mutation`
53
+ : never
54
+ ]: UseMutation<
51
55
  Extract<Definitions[K], MutationDefinition<any, any, any, any>>
52
56
  >
53
57
  }
@@ -1,9 +1,14 @@
1
1
  /**
2
- * If either :// or // is present consider it to be an absolute url
2
+ * Determines whether a url is absolute: it either starts with a scheme
3
+ * (`https://example.com`) or is protocol-relative (`//example.com`).
4
+ *
5
+ * The test is anchored to the start of the string on purpose. A relative url can
6
+ * legitimately carry an absolute one inside its query string, as in
7
+ * `redirect?target=https://example.com`, and treating that as absolute would make
8
+ * `joinUrls` drop the `baseUrl`.
3
9
  *
4
10
  * @param url string
5
11
  */
6
-
7
12
  export function isAbsoluteUrl(url: string) {
8
- return new RegExp(`(^|:)//`).test(url)
13
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
9
14
  }
@@ -243,7 +243,7 @@ export function createSerializableStateInvariantMiddleware(
243
243
  value,
244
244
  '\nTake a look at the logic that dispatched this action: ',
245
245
  action,
246
- '\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)',
246
+ '\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-why-should-my-action-types-be-constants)',
247
247
  '\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)',
248
248
  )
249
249
  }