Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bundling adjustments to create apis that can be referenced in rsc #4675

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@
"36": "When using custom hooks for context, all hooks need to be provided: .\\nHook was either not provided or not a function.",
"37": "Warning: Middleware for RTK-Query API at reducerPath \"\" has not been added to the store.\n You must add the middleware for RTK-Query to function correctly!",
"38": "Cannot refetch a query that has not been started yet.",
"39": "called \\`injectEndpoints\\` to override already-existing endpointName without specifying \\`overrideExisting: true\\`"
"39": "called \\`injectEndpoints\\` to override already-existing endpointName without specifying \\`overrideExisting: true\\`",
"40": "Hooks can only be used in Client Components"
}
4 changes: 4 additions & 0 deletions packages/toolkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
},
"./query/react": {
"types": "./dist/query/react/index.d.ts",
"react-server": {
"import": "./dist/query/react.rsc/rtk-query-react.modern.mjs",
"default": "./dist/query/react.rsc/cjs/index.js"
},
"import": "./dist/query/react/rtk-query-react.modern.mjs",
"default": "./dist/query/react/cjs/index.js"
}
Expand Down
46 changes: 46 additions & 0 deletions packages/toolkit/src/query/react/index.rsc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This must remain here so that the `mangleErrors.cjs` build script
// does not have to import this into each source file it rewrites.
import { formatProdErrorMessage } from '@reduxjs/toolkit'

import { buildCreateApi, coreModule } from '@reduxjs/toolkit/query'
import { unboundHooksModule, reactHooksModuleName } from './module'

export * from '@reduxjs/toolkit/query'
export { ApiProvider } from './ApiProvider'

const throwFn = () => {
throw new Error('Hooks can only be used in Client Components')
}

const reactHooksModule = unboundHooksModule({
hooks: {
useDispatch: throwFn,
useSelector: throwFn,
useStore: throwFn,
},
batch: throwFn,
})

const createApi = /* @__PURE__ */ buildCreateApi(
coreModule(),
reactHooksModule()
)

export type {
TypedUseMutationResult,
TypedUseQueryHookResult,
TypedUseQueryStateResult,
TypedUseQuerySubscriptionResult,
TypedLazyQueryTrigger,
TypedUseLazyQuery,
TypedUseMutation,
TypedMutationTrigger,
TypedQueryStateSelector,
TypedUseQueryState,
TypedUseQuery,
TypedUseQuerySubscription,
TypedUseLazyQuerySubscription,
TypedUseQueryStateOptions,
} from './buildHooks'
export { UNINITIALIZED_VALUE } from './constants'
export { createApi, reactHooksModule, reactHooksModuleName }
14 changes: 12 additions & 2 deletions packages/toolkit/src/query/react/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
// This must remain here so that the `mangleErrors.cjs` build script
// does not have to import this into each source file it rewrites.
import { formatProdErrorMessage } from '@reduxjs/toolkit'
import { batch, useDispatch, useSelector, useStore } from 'react-redux'

import { buildCreateApi, coreModule } from '@reduxjs/toolkit/query'
import { reactHooksModule, reactHooksModuleName } from './module'
import { unboundHooksModule, reactHooksModuleName } from './module'

export * from '@reduxjs/toolkit/query'
export { ApiProvider } from './ApiProvider'

const reactHooksModule = unboundHooksModule({
hooks: {
useDispatch,
useSelector,
useStore,
},
batch,
})

const createApi = /* @__PURE__ */ buildCreateApi(
coreModule(),
reactHooksModule(),
reactHooksModule()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
reactHooksModule()
reactHooksModule(),

)

export type {
Expand Down
202 changes: 99 additions & 103 deletions packages/toolkit/src/query/react/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ import type {
QueryDefinition,
QueryKeys,
} from '@reduxjs/toolkit/query'
import {
batch as rrBatch,
useDispatch as rrUseDispatch,
useSelector as rrUseSelector,
useStore as rrUseStore,
} from 'react-redux'

import { createSelector as _createSelector } from 'reselect'
import { isMutationDefinition, isQueryDefinition } from '../endpointDefinitions'
import { safeAssign } from '../tsHelpers'
Expand All @@ -34,7 +29,7 @@ declare module '@reduxjs/toolkit/query' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ReducerPath extends string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
TagTypes extends string,
TagTypes extends string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TagTypes extends string
TagTypes extends string,

> {
[reactHooksModuleName]: {
/**
Expand All @@ -50,15 +45,15 @@ declare module '@reduxjs/toolkit/query' {
>
? QueryHooks<Definitions[K]>
: Definitions[K] extends MutationDefinition<any, any, any, any, any>
? MutationHooks<Definitions[K]>
: never
? MutationHooks<Definitions[K]>
: never
}
/**
* A hook that accepts a string endpoint name, and provides a callback that when called, pre-fetches the data for that endpoint.
*/
usePrefetch<EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
options?: PrefetchOptions,
options?: PrefetchOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
options?: PrefetchOptions
options?: PrefetchOptions,

): (
arg: QueryArgFrom<Definitions[EndpointName]>,
options?: PrefetchOptions,
Expand Down Expand Up @@ -136,103 +131,104 @@ export interface ReactHooksModuleOptions {
*
* @returns A module for use with `buildCreateApi`
*/
export const reactHooksModule = ({
batch = rrBatch,
hooks = {
useDispatch: rrUseDispatch,
useSelector: rrUseSelector,
useStore: rrUseStore,
},
createSelector = _createSelector,
unstable__sideEffectsInRender = false,
...rest
}: ReactHooksModuleOptions = {}): Module<ReactHooksModule> => {
if (process.env.NODE_ENV !== 'production') {
const hookNames = ['useDispatch', 'useSelector', 'useStore'] as const
let warned = false
for (const hookName of hookNames) {
// warn for old hook options
if (countObjectKeys(rest) > 0) {
if ((rest as Partial<typeof hooks>)[hookName]) {
if (!warned) {
console.warn(
'As of RTK 2.0, the hooks now need to be specified as one object, provided under a `hooks` key:' +
'\n`reactHooksModule({ hooks: { useDispatch, useSelector, useStore } })`',
)
warned = true
export const unboundHooksModule =
({
batch: defaultBatch,
hooks: defaultHooks,
}: Required<Pick<ReactHooksModuleOptions, 'batch' | 'hooks'>>) =>
({
batch = defaultBatch,
hooks = defaultHooks,
createSelector = _createSelector,
unstable__sideEffectsInRender = false,
...rest
}: ReactHooksModuleOptions = {}): Module<ReactHooksModule> => {
if (process.env.NODE_ENV !== 'production') {
const hookNames = ['useDispatch', 'useSelector', 'useStore'] as const
let warned = false
for (const hookName of hookNames) {
// warn for old hook options
if (countObjectKeys(rest) > 0) {
if ((rest as Partial<typeof hooks>)[hookName]) {
if (!warned) {
console.warn(
'As of RTK 2.0, the hooks now need to be specified as one object, provided under a `hooks` key:' +
'\n`reactHooksModule({ hooks: { useDispatch, useSelector, useStore } })`'
)
warned = true
}
}
// migrate
// @ts-ignore
hooks[hookName] = rest[hookName]
}
// then make sure we have them all
if (typeof hooks[hookName] !== 'function') {
throw new Error(
`When using custom hooks for context, all ${
hookNames.length
} hooks need to be provided: ${hookNames.join(
', '
)}.\nHook ${hookName} was either not provided or not a function.`
)
}
// migrate
// @ts-ignore
hooks[hookName] = rest[hookName]
}
// then make sure we have them all
if (typeof hooks[hookName] !== 'function') {
throw new Error(
`When using custom hooks for context, all ${
hookNames.length
} hooks need to be provided: ${hookNames.join(
', ',
)}.\nHook ${hookName} was either not provided or not a function.`,
)
}
}
}

return {
name: reactHooksModuleName,
init(api, { serializeQueryArgs }, context) {
const anyApi = api as any as Api<
any,
Record<string, any>,
any,
any,
ReactHooksModule
>
const { buildQueryHooks, buildMutationHook, usePrefetch } = buildHooks({
api,
moduleOptions: {
batch,
hooks,
unstable__sideEffectsInRender,
createSelector,
},
serializeQueryArgs,
context,
})
safeAssign(anyApi, { usePrefetch })
safeAssign(context, { batch })
return {
name: reactHooksModuleName,
init(api, { serializeQueryArgs }, context) {
const anyApi = api as any as Api<
any,
Record<string, any>,
any,
any,
ReactHooksModule
>
const { buildQueryHooks, buildMutationHook, usePrefetch } = buildHooks({
api,
moduleOptions: {
batch,
hooks,
unstable__sideEffectsInRender,
createSelector,
},
serializeQueryArgs,
context,
})
safeAssign(anyApi, { usePrefetch })
safeAssign(context, { batch })

return {
injectEndpoint(endpointName, definition) {
if (isQueryDefinition(definition)) {
const {
useQuery,
useLazyQuery,
useLazyQuerySubscription,
useQueryState,
useQuerySubscription,
} = buildQueryHooks(endpointName)
safeAssign(anyApi.endpoints[endpointName], {
useQuery,
useLazyQuery,
useLazyQuerySubscription,
useQueryState,
useQuerySubscription,
})
;(api as any)[`use${capitalize(endpointName)}Query`] = useQuery
;(api as any)[`useLazy${capitalize(endpointName)}Query`] =
useLazyQuery
} else if (isMutationDefinition(definition)) {
const useMutation = buildMutationHook(endpointName)
safeAssign(anyApi.endpoints[endpointName], {
useMutation,
})
;(api as any)[`use${capitalize(endpointName)}Mutation`] =
useMutation
}
},
}
},
return {
injectEndpoint(endpointName, definition) {
if (isQueryDefinition(definition)) {
const {
useQuery,
useLazyQuery,
useLazyQuerySubscription,
useQueryState,
useQuerySubscription,
} = buildQueryHooks(endpointName)
safeAssign(anyApi.endpoints[endpointName], {
useQuery,
useLazyQuery,
useLazyQuerySubscription,
useQueryState,
useQuerySubscription,
})
;(api as any)[`use${capitalize(endpointName)}Query`] = useQuery
;(api as any)[`useLazy${capitalize(endpointName)}Query`] =
useLazyQuery
} else if (isMutationDefinition(definition)) {
const useMutation = buildMutationHook(endpointName)
safeAssign(anyApi.endpoints[endpointName], {
useMutation,
})
;(api as any)[`use${capitalize(endpointName)}Mutation`] =
useMutation
}
},
}
},
}
}
}
7 changes: 7 additions & 0 deletions packages/toolkit/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ const entryPoints: EntryPointOptions[] = [
extractionConfig: 'api-extractor.query-react.json',
externals: ['redux', '@reduxjs/toolkit'],
},
{
prefix: 'rtk-query-react',
folder: 'query/react.rsc',
entryPoint: 'src/query/react/index.rsc.ts',
extractionConfig: 'api-extractor.query-react.json',
externals: ['redux', '@reduxjs/toolkit'],
},
]

function writeCommonJSEntry(folder: string, prefix: string) {
Expand Down
Loading