diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 5a71532bbb..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,61 +0,0 @@ -module.exports = { - extends: ['react-app', 'prettier'], - parser: '@typescript-eslint/parser', - rules: { - 'jsx-a11y/href-no-hash': 'off', - 'react/react-in-jsx-scope': 'off', - // Taken care of by TypeScript's `noUnusedLocals` / `noUnusedParameters` - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': 'off', - // Silence some bizarre "rule not found" TSLint error - '@typescript-eslint/no-angle-bracket-type-assertion': 'off', - 'no-redeclare': 'off', - // Silence some bizarre "rule not found" TSLint error - '@typescript-eslint/no-redeclare': 'off', - 'no-use-before-define': 'off', - '@typescript-eslint/no-use-before-define': ['error', { functions: false }], - '@typescript-eslint/consistent-type-imports': [ - 'error', - { prefer: 'type-imports', disallowTypeAnnotations: false }, - ], - 'react-hooks/exhaustive-deps': [ - 'warn', - { - additionalHooks: '(usePossiblyImmediateEffect)', - }, - ], - }, - overrides: [ - // { - // // only add after https://github.com/typescript-eslint/typescript-eslint/pull/3463 is merged - // files: ['src/**/*.ts'], - // excludedFiles: [ - // '**/tests/*.ts', - // '**/tests/**/*.ts', - // '**/tests/*.tsx', - // '**/tests/**/*.tsx', - // ], - // parserOptions: { - // project: './tsconfig.json', - // }, - // rules: { - // '@typescript-eslint/prefer-readonly-parameter-types': [ - // 'warn', - // { arraysAndTuplesOnly: true }, - // ], - // }, - // }, - { - files: [ - 'packages/toolkit/src/tests/*.ts', - 'packages/toolkit/src/**/tests/*.ts', - 'packages/toolkit/src/**/tests/*.tsx', - ], - rules: { - '@typescript-eslint/no-unused-expressions': 'off', - 'no-lone-blocks': 'off', - 'no-sequences': 'off', - }, - }, - ], -} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 703b68cb09..3ed8da42b7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,6 +14,10 @@ on: - '@rtk-query/codegen-openapi' - '@rtk-query/graphql-request-base-query' - '@reduxjs/rtk-codemods' + - '@reduxjs/eslint-config' + - '@reduxjs/prettier-config' + - '@reduxjs/tsconfig' + - '@reduxjs/vitest-config' jobs: publish: runs-on: ubuntu-latest @@ -28,7 +32,7 @@ jobs: registry-url: 'https://registry.npmjs.org' cache: 'yarn' - run: yarn install --frozen-lockfile - - run: yarn workspace ${{ inputs.package }} test + - run: yarn workspaces foreach --include "${{ inputs.package }}" run test - run: yarn workspace ${{ inputs.package }} exec npm publish --access public --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml new file mode 100644 index 0000000000..baa9908dac --- /dev/null +++ b/.github/workflows/test-configs.yml @@ -0,0 +1,117 @@ +name: Test Configs + +on: [push, pull_request, workflow_dispatch] + +jobs: + test-types: + name: Test types with TypeScript ${{ matrix.ts }} on ${{ matrix.os }} and Node.js ${{ matrix.node }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + + matrix: + package: + [ + '@reduxjs/eslint-config', + '@reduxjs/prettier-config', + '@reduxjs/vitest-config', + ] + node: ['22.x'] + os: [ubuntu-latest] + ts: ['5.3', '5.4', '5.5', '5.6', '5.7', '5.8'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use node ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'yarn' + + - name: Install dependencies + run: yarn install + + - name: Install TypeScript ${{ matrix.ts }} + run: yarn up typescript@${{ matrix.ts }} + + - name: Run type tests + run: yarn workspace ${{ matrix.package }} run test-types + + are-the-types-wrong: + name: Check if the type definitions for ${{ matrix.package }} are correct with Node.js ${{ matrix.node }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + + matrix: + node: ['22.x'] + package: + [ + '@reduxjs/eslint-config', + '@reduxjs/prettier-config', + '@reduxjs/tsconfig', + '@reduxjs/vitest-config', + ] + os: [ubuntu-latest] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use node ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'yarn' + + - name: Install dependencies + run: yarn install + + - name: Run are-the-types-wrong for ${{ matrix.package }} with Node.js ${{ matrix.node }} on ${{ matrix.os }} + run: yarn workspace ${{ matrix.package }} run check-exports --format table + + - name: Did we fail? + if: failure() + run: ls -R + + publint: + name: Check if the package.json for ${{ matrix.package }} is correct with Node.js ${{ matrix.node }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + + matrix: + node: ['22.x'] + package: + [ + '@reduxjs/eslint-config', + '@reduxjs/prettier-config', + '@reduxjs/tsconfig', + '@reduxjs/vitest-config', + ] + os: [ubuntu-latest] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use node ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'yarn' + + - name: Install dependencies + run: yarn install + + - name: Run publint for ${{ matrix.package }} with Node.js ${{ matrix.node }} on ${{ matrix.os }} + run: yarn workspace ${{ matrix.package }} run check-package-json + + - name: Did we fail? + if: failure() + run: ls -R diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 46f9d3475b..f9053629be 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,6 +46,12 @@ jobs: - name: Install deps run: yarn install + - name: Check formatting + run: yarn workspaces foreach -Ap -j unlimited run format-check + + - name: Lint files + run: yarn workspaces foreach -Ap -j unlimited run lint + # Read existing version, reuse that, add a Git short hash - name: Set build version to Git commit run: yarn tsx scripts/writeGitVersion.mts $(git rev-parse --short HEAD) diff --git a/.gitignore b/.gitignore index a8309316f0..f5d34d6e00 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ typesversions .pnp.* *.tgz -tsconfig.vitest-temp.json \ No newline at end of file +tsconfig.vitest-temp.json +.eslintcache diff --git a/.prettierignore b/.prettierignore index 46179d7498..d2ba6ec0a6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ -**/dist/** -**/etc/** -**/temp/** -**/__testfixtures__/** \ No newline at end of file +__testfixtures__/ +.docusaurus/ +.next/ +examples/publish-ci/ +.yarn/ diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index b2095be81e..0000000000 --- a/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "semi": false, - "singleQuote": true -} diff --git a/docs/api/actionCreatorMiddleware.mdx b/docs/api/actionCreatorMiddleware.mdx index fede5df8c3..16281ade91 100644 --- a/docs/api/actionCreatorMiddleware.mdx +++ b/docs/api/actionCreatorMiddleware.mdx @@ -54,7 +54,7 @@ import reducer from './reducer' // Augment middleware to consider all functions with a static type property to be action creators const isActionCreator = ( action: unknown, -): action is Function & { type: unknown } => +): action is (...args: any) => any & { type: unknown } => typeof action === 'function' && 'type' in action const actionCreatorMiddleware = createActionCreatorInvariantMiddleware({ diff --git a/docs/api/createListenerMiddleware.mdx b/docs/api/createListenerMiddleware.mdx index a805e2ebe9..51084b831f 100644 --- a/docs/api/createListenerMiddleware.mdx +++ b/docs/api/createListenerMiddleware.mdx @@ -488,7 +488,7 @@ To fix this, the middleware provides types for defining "pre-typed" versions of import { createListenerMiddleware, addListener } from '@reduxjs/toolkit' import type { RootState, AppDispatch } from './store' -declare type ExtraArgument = {foo: string}; +declare type ExtraArgument = { foo: string } export const listenerMiddleware = createListenerMiddleware() diff --git a/docs/package.json b/docs/package.json index 72b17dc4e2..248afa276e 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,6 +2,7 @@ "name": "docs", "devDependencies": { "@manaflair/redux-batch": "^1.0.0", + "@reduxjs/tsconfig": "workspace:^", "@types/nanoid": "^2.1.0", "@types/react": "^19.0.1", "async-mutex": "^0.3.2", @@ -12,6 +13,7 @@ "nanoid": "^3.1.23", "next-redux-wrapper": "^7.0.5", "redux-persist": "^6.0.0", - "rxjs": "^6.6.2" + "rxjs": "^6.6.2", + "typescript": "^5.8.2" } } diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 5692743ab2..05b4334a35 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "@reduxjs/tsconfig/base", "compilerOptions": { "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/docs/virtual/matchers/index.ts b/docs/virtual/matchers/index.ts index aba086bcf5..8f2453871c 100644 --- a/docs/virtual/matchers/index.ts +++ b/docs/virtual/matchers/index.ts @@ -1,8 +1,5 @@ -import { - createAsyncThunk, - createReducer, - PayloadAction, -} from '@reduxjs/toolkit' +import type { PayloadAction } from '@reduxjs/toolkit' +import { createAsyncThunk, createReducer } from '@reduxjs/toolkit' export interface Data { isInteresting: boolean diff --git a/docs/virtual/petstore-api.generated/petstore-api.generated.ts b/docs/virtual/petstore-api.generated/petstore-api.generated.ts index c885323c48..1bba1ce78b 100644 --- a/docs/virtual/petstore-api.generated/petstore-api.generated.ts +++ b/docs/virtual/petstore-api.generated/petstore-api.generated.ts @@ -123,6 +123,7 @@ export const api = createApi({ }), }), }) +type AnyNonNullishValue = NonNullable export type UpdatePetApiResponse = /** status 200 Successful operation */ Pet export type UpdatePetApiArg = { /** Update an existent pet in the store */ @@ -174,10 +175,9 @@ export type UploadFileApiArg = { additionalMetadata?: string body: string } -export type GetInventoryApiResponse = /** status 200 successful operation */ { - [key: string]: number -} -export type GetInventoryApiArg = {} +export type GetInventoryApiResponse = + /** status 200 successful operation */ Record +export type GetInventoryApiArg = AnyNonNullishValue export type PlaceOrderApiResponse = /** status 200 successful operation */ Order export type PlaceOrderApiArg = { order: Order @@ -211,7 +211,7 @@ export type LoginUserApiArg = { password?: string } export type LogoutUserApiResponse = unknown -export type LogoutUserApiArg = {} +export type LogoutUserApiArg = AnyNonNullishValue export type GetUserByNameApiResponse = /** status 200 successful operation */ User export type GetUserByNameApiArg = { diff --git a/errors.json b/errors.json index 8169973800..da47188438 100644 --- a/errors.json +++ b/errors.json @@ -42,4 +42,4 @@ "40": "maxPages for endpoint '' must be a number greater than 0", "41": "getPreviousPageParam for endpoint '' must be a function if maxPages is used", "42": "Duplicate middleware references found when creating the store. Ensure that each middleware is only included once." -} \ No newline at end of file +} diff --git a/eslint.config.mts b/eslint.config.mts new file mode 100644 index 0000000000..e26cfaf14a --- /dev/null +++ b/eslint.config.mts @@ -0,0 +1,103 @@ +import { createESLintConfig } from '@reduxjs/eslint-config' +import eslintConfigPackageJson from '@reduxjs/eslint-config/package.json' with { type: 'json' } + +const basename = `${eslintConfigPackageJson.name}/overrides` + +const eslintConfig = createESLintConfig([ + { + name: `${basename}/global-ignores`, + ignores: [ + 'packages/rtk-codemods/transforms/*/__testfixtures__/', + 'packages/toolkit/.size-limit.cjs', + 'packages/rtk-query-codegen-openapi/test/config.example.js', + 'examples/publish-ci/', + + // TODO: Remove this later. + 'examples/', + ], + }, + + { + name: `${basename}/main`, + files: ['**/*.?(c|m)[jt]s?(x)'], + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + // TODO: Enable this later. + '@typescript-eslint/consistent-type-definitions': [0, 'type'], + '@typescript-eslint/prefer-nullish-coalescing': [0], + '@typescript-eslint/no-namespace': [0], + '@typescript-eslint/require-await': [0], + '@typescript-eslint/unified-signatures': [0], + '@typescript-eslint/no-unnecessary-type-parameters': [0], + '@typescript-eslint/no-invalid-void-type': [0], + '@typescript-eslint/no-unnecessary-type-arguments': [0], + '@typescript-eslint/no-confusing-void-expression': [0], + '@typescript-eslint/no-duplicate-type-constituents': [0], + '@typescript-eslint/no-redundant-type-constituents': [0], + '@typescript-eslint/no-unnecessary-type-assertion': [0], + 'object-shorthand': [0], + '@typescript-eslint/no-explicit-any': [ + 0, + { + fixToUnknown: false, + ignoreRestArgs: false, + }, + ], + }, + }, + + { + name: `${basename}/vitest-custom-matchers-declaration-file`, + files: ['packages/toolkit/src/tests/utils/CustomMatchers.d.ts'], + rules: { + '@typescript-eslint/no-empty-object-type': [ + 2, + { + allowInterfaces: 'with-single-extends', + allowObjectTypes: 'never', + }, + ], + }, + }, + + { + name: `${basename}/no-require-imports`, + files: ['examples/query/react/graphql-codegen/src/mocks/schema.js'], + languageOptions: { + sourceType: 'commonjs', + }, + rules: { + '@typescript-eslint/no-require-imports': [ + 2, + { + allow: ['ts-node', '\\./db(.c?[tj]s)?$'], + allowAsImport: false, + }, + ], + }, + }, + + { + name: `${basename}/examples/type-portability/nodenext-cjs`, + files: ['examples/type-portability/nodenext-cjs/**/*.?(c)ts?(x)'], + languageOptions: { + sourceType: 'commonjs', + }, + rules: { + '@typescript-eslint/no-namespace': [ + 0, + { + allowDeclarations: false, + allowDefinitionFiles: true, + }, + ], + }, + }, +]) + +export default eslintConfig diff --git a/examples/action-listener/counter/package.json b/examples/action-listener/counter/package.json index 925ec93bd9..b67db94391 100644 --- a/examples/action-listener/counter/package.json +++ b/examples/action-listener/counter/package.json @@ -41,6 +41,7 @@ ] }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "jest-watch-typeahead": "^1.1.0" } } diff --git a/examples/action-listener/counter/src/components/App/App.tsx b/examples/action-listener/counter/src/components/App/App.tsx index ca09482b2b..52778a0525 100644 --- a/examples/action-listener/counter/src/components/App/App.tsx +++ b/examples/action-listener/counter/src/components/App/App.tsx @@ -1,12 +1,12 @@ +import type { Unsubscribe } from '@reduxjs/toolkit' import React, { useEffect } from 'react' import { Provider } from 'react-redux' -import type { Unsubscribe } from '@reduxjs/toolkit' -import { setupThemeListeners } from '../../services/theme/listeners' import { setupCounterListeners } from '../../services/counter/listeners' +import { setupThemeListeners } from '../../services/theme/listeners' +import { startAppListening, store } from '../../store' import { ChangeThemeForm } from '../ChangeThemeForm/ChangeThemeForm' import { CounterList } from '../CounterList/CounterList' import { CreateCounterForm } from '../CreateCounterForm/CreateCounterForm' -import { store, startAppListening } from '../../store' export function App() { useEffect(() => { diff --git a/examples/action-listener/counter/src/components/ChangeThemeForm/ChangeThemeForm.tsx b/examples/action-listener/counter/src/components/ChangeThemeForm/ChangeThemeForm.tsx index 5916c338d5..9d05de219d 100644 --- a/examples/action-listener/counter/src/components/ChangeThemeForm/ChangeThemeForm.tsx +++ b/examples/action-listener/counter/src/components/ChangeThemeForm/ChangeThemeForm.tsx @@ -1,6 +1,7 @@ -import { FormEvent, ChangeEvent } from 'react' +import type { ChangeEvent, FormEvent } from 'react' +import type { ThemeState } from '../../services/theme/slice' +import { themeActions } from '../../services/theme/slice' import { useAppDispatch, useAppSelector } from '../../store' -import { themeActions, ThemeState } from '../../services/theme/slice' import styles from './changeThemeForm.module.css' function isChecked(theme: ThemeState): boolean { diff --git a/examples/action-listener/counter/src/components/Counter/Counter.tsx b/examples/action-listener/counter/src/components/Counter/Counter.tsx index 92a878c0c5..0f18df3074 100644 --- a/examples/action-listener/counter/src/components/Counter/Counter.tsx +++ b/examples/action-listener/counter/src/components/Counter/Counter.tsx @@ -1,9 +1,9 @@ -import { EntityId } from '@reduxjs/toolkit' +import type { EntityId } from '@reduxjs/toolkit' +import clsx from 'clsx' import { memo } from 'react' import { counterActions, counterSelectors } from '../../services/counter/slice' import { useAppDispatch, useAppSelector } from '../../store' import styles from './counter.module.css' -import clsx from 'clsx' export interface CounterProps { counterId: EntityId diff --git a/examples/action-listener/counter/src/components/CreateCounterForm/CreateCounterForm.tsx b/examples/action-listener/counter/src/components/CreateCounterForm/CreateCounterForm.tsx index 250afcf188..21574db355 100644 --- a/examples/action-listener/counter/src/components/CreateCounterForm/CreateCounterForm.tsx +++ b/examples/action-listener/counter/src/components/CreateCounterForm/CreateCounterForm.tsx @@ -1,8 +1,9 @@ -import { FormEvent, useState } from 'react' -import styles from './createCounter.module.css' import clsx from 'clsx' -import { useAppDispatch } from '../../store' +import type { FormEvent } from 'react' +import { useState } from 'react' import { counterActions } from '../../services/counter/slice' +import { useAppDispatch } from '../../store' +import styles from './createCounter.module.css' const sectionClassname = clsx('paper', styles.section) diff --git a/examples/action-listener/counter/src/index.css b/examples/action-listener/counter/src/index.css index cc09e5d2c9..0b52d120a7 100644 --- a/examples/action-listener/counter/src/index.css +++ b/examples/action-listener/counter/src/index.css @@ -1,15 +1,15 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } h1 { diff --git a/examples/action-listener/counter/src/services/counter/listeners.ts b/examples/action-listener/counter/src/services/counter/listeners.ts index 4c2f6db754..8bf96359b1 100644 --- a/examples/action-listener/counter/src/services/counter/listeners.ts +++ b/examples/action-listener/counter/src/services/counter/listeners.ts @@ -1,12 +1,11 @@ -import { counterActions, counterSelectors } from './slice' -import { - UnknownAction, - isAllOf, - isAnyOf, +import type { PayloadAction, + UnknownAction, Unsubscribe, } from '@reduxjs/toolkit' +import { isAllOf, isAnyOf } from '@reduxjs/toolkit' import type { AppListenerEffectAPI, AppStartListening } from '../../store' +import { counterActions, counterSelectors } from './slice' function shouldStopAsyncTasksOf(id: string) { return isAllOf( diff --git a/examples/action-listener/counter/src/services/counter/slice.ts b/examples/action-listener/counter/src/services/counter/slice.ts index fbd8680606..17b6455345 100644 --- a/examples/action-listener/counter/src/services/counter/slice.ts +++ b/examples/action-listener/counter/src/services/counter/slice.ts @@ -1,9 +1,5 @@ -import { - createSlice, - createEntityAdapter, - nanoid, - PayloadAction, -} from '@reduxjs/toolkit' +import type { PayloadAction } from '@reduxjs/toolkit' +import { createEntityAdapter, createSlice, nanoid } from '@reduxjs/toolkit' export interface Counter { value: number @@ -70,7 +66,9 @@ export const counterSlice = createSlice({ updateByAsync( _, action: PayloadAction<{ id: string; delta: number; delayMs: number }>, - ) {}, + ) { + /* No-Op */ + }, cancelAsyncUpdates(state, { payload }: PayloadAction) { delete state.counters.entities[payload]?.intervalMs }, diff --git a/examples/action-listener/counter/src/services/counter/tests/listener.test.ts b/examples/action-listener/counter/src/services/counter/tests/listener.test.ts index c5ef961322..b8858c6a5c 100644 --- a/examples/action-listener/counter/src/services/counter/tests/listener.test.ts +++ b/examples/action-listener/counter/src/services/counter/tests/listener.test.ts @@ -1,7 +1,7 @@ import { configureStore, createListenerMiddleware } from '@reduxjs/toolkit' -import { setupCounterListeners } from '../listeners' -import { counterSlice, counterActions, counterSelectors } from '../slice' import type { AppStartListening } from '../../../store' +import { setupCounterListeners } from '../listeners' +import { counterActions, counterSelectors, counterSlice } from '../slice' function delay(timerMs: number): Promise { return new Promise((resolve) => { @@ -12,7 +12,9 @@ function delay(timerMs: number): Promise { jest.useRealTimers() describe('counter - listeners', () => { - const onMiddlewareError = jest.fn((): void => {}) // https://jestjs.io/docs/mock-function-api + const onMiddlewareError = jest.fn((): void => { + /* No-Op */ + }) // https://jestjs.io/docs/mock-function-api /** * @see https://redux-toolkit.js.org/api/createListenerMiddleware diff --git a/examples/action-listener/counter/src/services/theme/listeners.ts b/examples/action-listener/counter/src/services/theme/listeners.ts index 2cbbdd0b87..7834cdbf17 100644 --- a/examples/action-listener/counter/src/services/theme/listeners.ts +++ b/examples/action-listener/counter/src/services/theme/listeners.ts @@ -1,6 +1,6 @@ -import { themeActions } from './slice' +import type { Unsubscribe } from '@reduxjs/toolkit' import type { AppStartListening } from '../../store' -import { Unsubscribe } from '@reduxjs/toolkit' +import { themeActions } from './slice' function onChangeColorScheme( action: ReturnType, diff --git a/examples/action-listener/counter/src/store.ts b/examples/action-listener/counter/src/store.ts index 8abb0ea3a7..06ae7d9a11 100644 --- a/examples/action-listener/counter/src/store.ts +++ b/examples/action-listener/counter/src/store.ts @@ -1,12 +1,15 @@ -import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import type { + ListenerEffectAPI, + TypedAddListener, + TypedStartListening, +} from '@reduxjs/toolkit' import { + addListener, configureStore, createListenerMiddleware, - TypedStartListening, - TypedAddListener, - ListenerEffectAPI, - addListener, } from '@reduxjs/toolkit' +import type { TypedUseSelectorHook } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { counterSlice } from './services/counter/slice' import { themeSlice } from './services/theme/slice' diff --git a/examples/action-listener/counter/tsconfig.json b/examples/action-listener/counter/tsconfig.json index 9d379a3c4a..6812fef180 100644 --- a/examples/action-listener/counter/tsconfig.json +++ b/examples/action-listener/counter/tsconfig.json @@ -1,20 +1,5 @@ { - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, "include": ["src"] } diff --git a/examples/publish-ci/cra4/src/index.css b/examples/publish-ci/cra4/src/index.css index ec2585e8c0..84640987c3 100644 --- a/examples/publish-ci/cra4/src/index.css +++ b/examples/publish-ci/cra4/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } diff --git a/examples/publish-ci/cra5/src/index.css b/examples/publish-ci/cra5/src/index.css index ec2585e8c0..84640987c3 100644 --- a/examples/publish-ci/cra5/src/index.css +++ b/examples/publish-ci/cra5/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } diff --git a/examples/publish-ci/vite/src/index.css b/examples/publish-ci/vite/src/index.css index ec2585e8c0..84640987c3 100644 --- a/examples/publish-ci/vite/src/index.css +++ b/examples/publish-ci/vite/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } diff --git a/examples/query/react/advanced/package.json b/examples/query/react/advanced/package.json index 79669621be..788991c1ca 100644 --- a/examples/query/react/advanced/package.json +++ b/examples/query/react/advanced/package.json @@ -13,6 +13,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "typescript": "^5.8.2" diff --git a/examples/query/react/advanced/tsconfig.json b/examples/query/react/advanced/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/advanced/tsconfig.json +++ b/examples/query/react/advanced/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/authentication-with-extrareducers/package.json b/examples/query/react/authentication-with-extrareducers/package.json index bc59220744..2ee89394ac 100644 --- a/examples/query/react/authentication-with-extrareducers/package.json +++ b/examples/query/react/authentication-with-extrareducers/package.json @@ -20,6 +20,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "typescript": "^5.8.2" diff --git a/examples/query/react/authentication-with-extrareducers/src/App.tsx b/examples/query/react/authentication-with-extrareducers/src/App.tsx index 9a8fbd70ca..872ed02025 100644 --- a/examples/query/react/authentication-with-extrareducers/src/App.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/App.tsx @@ -1,9 +1,8 @@ -import { Routes, Route } from 'react-router-dom' import { Box, Center, VStack } from '@chakra-ui/react' - +import { Route, Routes } from 'react-router-dom' import { Login } from './features/auth/Login' -import { PrivateOutlet } from './utils/PrivateOutlet' import { ProtectedComponent } from './features/auth/ProtectedComponent' +import { PrivateOutlet } from './utils/PrivateOutlet' function Hooray() { return ( diff --git a/examples/query/react/authentication-with-extrareducers/src/app/services/auth.ts b/examples/query/react/authentication-with-extrareducers/src/app/services/auth.ts index 371e6df347..9904691578 100644 --- a/examples/query/react/authentication-with-extrareducers/src/app/services/auth.ts +++ b/examples/query/react/authentication-with-extrareducers/src/app/services/auth.ts @@ -1,5 +1,5 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { RootState } from '../store' +import type { RootState } from '../store' export interface User { first_name: string diff --git a/examples/query/react/authentication-with-extrareducers/src/features/auth/Login.tsx b/examples/query/react/authentication-with-extrareducers/src/features/auth/Login.tsx index ce36f9bbf0..3e6df53c89 100644 --- a/examples/query/react/authentication-with-extrareducers/src/features/auth/Login.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/features/auth/Login.tsx @@ -1,21 +1,20 @@ -import * as React from 'react' import { + Box, + Button, + Center, + Divider, Input, InputGroup, InputRightElement, VStack, - Button, - Divider, - Center, - Box, useToast, } from '@chakra-ui/react' -import { useNavigate } from 'react-router-dom' +import * as React from 'react' import { useDispatch } from 'react-redux' - -import { ProtectedComponent } from './ProtectedComponent' -import { useLoginMutation } from '../../app/services/auth' +import { useNavigate } from 'react-router-dom' import type { LoginRequest } from '../../app/services/auth' +import { useLoginMutation } from '../../app/services/auth' +import { ProtectedComponent } from './ProtectedComponent' function PasswordInput({ name, diff --git a/examples/query/react/authentication-with-extrareducers/src/features/auth/ProtectedComponent.tsx b/examples/query/react/authentication-with-extrareducers/src/features/auth/ProtectedComponent.tsx index 1a63880717..d960b90993 100644 --- a/examples/query/react/authentication-with-extrareducers/src/features/auth/ProtectedComponent.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/features/auth/ProtectedComponent.tsx @@ -1,4 +1,4 @@ -import { Center, VStack, Box, Button } from '@chakra-ui/react' +import { Box, Button, Center, VStack } from '@chakra-ui/react' import { useProtectedMutation } from '../../app/services/auth' export function ProtectedComponent() { diff --git a/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx b/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx index dfbc2182ec..bece91f99f 100644 --- a/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx @@ -1,5 +1,6 @@ import { createSlice } from '@reduxjs/toolkit' -import { api, User } from '../../app/services/auth' +import type { User } from '../../app/services/auth' +import { api } from '../../app/services/auth' import type { RootState } from '../../app/store' type AuthState = { diff --git a/examples/query/react/authentication-with-extrareducers/src/hooks/store.ts b/examples/query/react/authentication-with-extrareducers/src/hooks/store.ts index 0be5471d1c..da9d6db3e1 100644 --- a/examples/query/react/authentication-with-extrareducers/src/hooks/store.ts +++ b/examples/query/react/authentication-with-extrareducers/src/hooks/store.ts @@ -1,4 +1,5 @@ -import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import type { TypedUseSelectorHook } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import type { AppDispatch, RootState } from '../app/store' export const useTypedSelector: TypedUseSelectorHook = useSelector diff --git a/examples/query/react/authentication-with-extrareducers/tsconfig.json b/examples/query/react/authentication-with-extrareducers/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/authentication-with-extrareducers/tsconfig.json +++ b/examples/query/react/authentication-with-extrareducers/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/authentication/package.json b/examples/query/react/authentication/package.json index e4a1e7a85f..e5b1a146e2 100644 --- a/examples/query/react/authentication/package.json +++ b/examples/query/react/authentication/package.json @@ -20,6 +20,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "typescript": "^5.8.2" diff --git a/examples/query/react/authentication/src/App.tsx b/examples/query/react/authentication/src/App.tsx index b5a6584be3..4313030b0a 100644 --- a/examples/query/react/authentication/src/App.tsx +++ b/examples/query/react/authentication/src/App.tsx @@ -1,9 +1,8 @@ -import { Routes, Route } from 'react-router-dom' import { Box, Center, VStack } from '@chakra-ui/react' - +import { Route, Routes } from 'react-router-dom' import { Login } from './features/auth/Login' -import { PrivateOutlet } from './utils/PrivateOutlet' import { ProtectedComponent } from './features/auth/ProtectedComponent' +import { PrivateOutlet } from './utils/PrivateOutlet' function Hooray() { return ( diff --git a/examples/query/react/authentication/src/app/services/auth.ts b/examples/query/react/authentication/src/app/services/auth.ts index 371e6df347..9904691578 100644 --- a/examples/query/react/authentication/src/app/services/auth.ts +++ b/examples/query/react/authentication/src/app/services/auth.ts @@ -1,5 +1,5 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { RootState } from '../store' +import type { RootState } from '../store' export interface User { first_name: string diff --git a/examples/query/react/authentication/src/features/auth/Login.tsx b/examples/query/react/authentication/src/features/auth/Login.tsx index 9089dee33e..7aeca17b46 100644 --- a/examples/query/react/authentication/src/features/auth/Login.tsx +++ b/examples/query/react/authentication/src/features/auth/Login.tsx @@ -1,22 +1,21 @@ -import * as React from 'react' import { + Box, + Button, + Center, + Divider, Input, InputGroup, InputRightElement, VStack, - Button, - Divider, - Center, - Box, useToast, } from '@chakra-ui/react' -import { useNavigate } from 'react-router-dom' +import * as React from 'react' import { useDispatch } from 'react-redux' +import { useNavigate } from 'react-router-dom' +import type { LoginRequest } from '../../app/services/auth' +import { useLoginMutation } from '../../app/services/auth' import { setCredentials } from './authSlice' - import { ProtectedComponent } from './ProtectedComponent' -import { useLoginMutation } from '../../app/services/auth' -import type { LoginRequest } from '../../app/services/auth' function PasswordInput({ name, diff --git a/examples/query/react/authentication/src/features/auth/ProtectedComponent.tsx b/examples/query/react/authentication/src/features/auth/ProtectedComponent.tsx index 1a63880717..d960b90993 100644 --- a/examples/query/react/authentication/src/features/auth/ProtectedComponent.tsx +++ b/examples/query/react/authentication/src/features/auth/ProtectedComponent.tsx @@ -1,4 +1,4 @@ -import { Center, VStack, Box, Button } from '@chakra-ui/react' +import { Box, Button, Center, VStack } from '@chakra-ui/react' import { useProtectedMutation } from '../../app/services/auth' export function ProtectedComponent() { diff --git a/examples/query/react/authentication/src/hooks/store.ts b/examples/query/react/authentication/src/hooks/store.ts index 0be5471d1c..da9d6db3e1 100644 --- a/examples/query/react/authentication/src/hooks/store.ts +++ b/examples/query/react/authentication/src/hooks/store.ts @@ -1,4 +1,5 @@ -import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import type { TypedUseSelectorHook } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import type { AppDispatch, RootState } from '../app/store' export const useTypedSelector: TypedUseSelectorHook = useSelector diff --git a/examples/query/react/authentication/tsconfig.json b/examples/query/react/authentication/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/authentication/tsconfig.json +++ b/examples/query/react/authentication/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/basic/package.json b/examples/query/react/basic/package.json index a0a6290270..a00faa242a 100644 --- a/examples/query/react/basic/package.json +++ b/examples/query/react/basic/package.json @@ -13,8 +13,9 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@testing-library/dom": "^10.4.0", - "@testing-library/react": "^16.1.0", + "@testing-library/react": "^16.3.0", "@types/jest": "^26.0.23", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", diff --git a/examples/query/react/basic/src/test/test-utils.tsx b/examples/query/react/basic/src/test/test-utils.tsx index 714b2b6a51..0804b1676b 100644 --- a/examples/query/react/basic/src/test/test-utils.tsx +++ b/examples/query/react/basic/src/test/test-utils.tsx @@ -1,11 +1,11 @@ -import { render } from '@testing-library/react' +import type { PreloadedState } from '@reduxjs/toolkit' import type { RenderOptions } from '@testing-library/react' +import { render } from '@testing-library/react' import type React from 'react' -import type { PropsWithChildren, JSX } from 'react' +import type { JSX, PropsWithChildren } from 'react' import { Provider } from 'react-redux' -import { setupStore } from '../store' import type { AppStore, RootState } from '../store' -import type { PreloadedState } from '@reduxjs/toolkit' +import { setupStore } from '../store' // This type interface extends the default options for render from RTL, as well // as allows the user to specify other things such as initialState, store. For @@ -24,7 +24,7 @@ function renderWithProviders( ...renderOptions }: ExtendedRenderOptions = {}, ) { - function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element { + function Wrapper({ children }: PropsWithChildren): JSX.Element { return {children} } return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) } diff --git a/examples/query/react/basic/tsconfig.json b/examples/query/react/basic/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/basic/tsconfig.json +++ b/examples/query/react/basic/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/conditional-fetching/package.json b/examples/query/react/conditional-fetching/package.json index 085da4166a..374c4ddf01 100644 --- a/examples/query/react/conditional-fetching/package.json +++ b/examples/query/react/conditional-fetching/package.json @@ -13,6 +13,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "typescript": "^5.8.2" diff --git a/examples/query/react/conditional-fetching/src/App.tsx b/examples/query/react/conditional-fetching/src/App.tsx index 53c87863f3..43bd6643b8 100644 --- a/examples/query/react/conditional-fetching/src/App.tsx +++ b/examples/query/react/conditional-fetching/src/App.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import { Pokemon } from './Pokemon' -import { PokemonName, POKEMON_NAMES } from './pokemon.data' +import type { PokemonName } from './pokemon.data' +import { POKEMON_NAMES } from './pokemon.data' import './styles.css' const getRandomPokemonName = () => diff --git a/examples/query/react/conditional-fetching/tsconfig.json b/examples/query/react/conditional-fetching/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/conditional-fetching/tsconfig.json +++ b/examples/query/react/conditional-fetching/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/deduping-queries/package.json b/examples/query/react/deduping-queries/package.json index 210622c0b3..46d9b19cd8 100644 --- a/examples/query/react/deduping-queries/package.json +++ b/examples/query/react/deduping-queries/package.json @@ -13,6 +13,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "typescript": "^5.8.2" diff --git a/examples/query/react/deduping-queries/tsconfig.json b/examples/query/react/deduping-queries/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/deduping-queries/tsconfig.json +++ b/examples/query/react/deduping-queries/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/graphql-codegen/package.json b/examples/query/react/graphql-codegen/package.json index 8acba56a08..35c234dd6b 100644 --- a/examples/query/react/graphql-codegen/package.json +++ b/examples/query/react/graphql-codegen/package.json @@ -33,6 +33,7 @@ "@graphql-codegen/typescript-operations": "^1.18.0", "@graphql-codegen/typescript-rtk-query": "^1.1.0", "@graphql-typed-document-node/core": "^3.1.0", + "@reduxjs/tsconfig": "workspace:^", "@types/faker": "^5.5.5", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", diff --git a/examples/query/react/graphql-codegen/src/app/services/types.generated.ts b/examples/query/react/graphql-codegen/src/app/services/types.generated.ts index 399ebbd2c9..8300186423 100644 --- a/examples/query/react/graphql-codegen/src/app/services/types.generated.ts +++ b/examples/query/react/graphql-codegen/src/app/services/types.generated.ts @@ -1,5 +1,5 @@ export type Maybe = T -export type Exact = { +export type Exact> = { [K in keyof T]: T[K] } export type MakeOptional = Omit & { @@ -30,9 +30,9 @@ export type Mutation = { __typename?: 'Mutation' createPost?: Maybe updatePost?: Maybe - updatePosts?: Maybe>> + updatePosts?: Maybe[]> deletePost?: Maybe - deletePosts?: Maybe>> + deletePosts?: Maybe[]> } export type MutationCreatePostArgs = { @@ -94,7 +94,7 @@ export type PostQueryInput = { export type Query = { __typename?: 'Query' post?: Maybe - posts?: Maybe>> + posts?: Maybe[]> } export type QueryPostArgs = { diff --git a/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx b/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx index 82052c13f0..25f2773216 100644 --- a/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx +++ b/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx @@ -1,12 +1,11 @@ -import * as React from 'react' import { Badge, Box, Button, Divider, Flex, - Heading, HStack, + Heading, Icon, List, ListIcon, @@ -16,6 +15,7 @@ import { StatLabel, StatNumber, } from '@chakra-ui/react' +import * as React from 'react' import { MdArrowBack, MdArrowForward, MdBook } from 'react-icons/md' import { useGetPostsQuery } from './GetPosts.generated' diff --git a/examples/query/react/graphql-codegen/tsconfig.json b/examples/query/react/graphql-codegen/tsconfig.json index 4842cab6c4..6812fef180 100644 --- a/examples/query/react/graphql-codegen/tsconfig.json +++ b/examples/query/react/graphql-codegen/tsconfig.json @@ -1,21 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "baseUrl": "src" - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/graphql/package.json b/examples/query/react/graphql/package.json index ab6cee11a8..2d6d8852ac 100644 --- a/examples/query/react/graphql/package.json +++ b/examples/query/react/graphql/package.json @@ -25,6 +25,7 @@ "react-scripts": "5.0.1" }, "devDependencies": { + "@reduxjs/tsconfig": "workspace:^", "@types/faker": "^5.5.5", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", diff --git a/examples/query/react/graphql/src/features/posts/PostsManager.tsx b/examples/query/react/graphql/src/features/posts/PostsManager.tsx index da92a4eea6..cbf74efb29 100644 --- a/examples/query/react/graphql/src/features/posts/PostsManager.tsx +++ b/examples/query/react/graphql/src/features/posts/PostsManager.tsx @@ -1,12 +1,11 @@ -import * as React from 'react' import { Badge, Box, Button, Divider, Flex, - Heading, HStack, + Heading, Icon, List, ListIcon, @@ -16,8 +15,10 @@ import { StatLabel, StatNumber, } from '@chakra-ui/react' +import * as React from 'react' import { MdArrowBack, MdArrowForward, MdBook } from 'react-icons/md' -import { Post, useGetPostsQuery } from '../../app/services/posts' +import type { Post } from '../../app/services/posts' +import { useGetPostsQuery } from '../../app/services/posts' const getColorForStatus = (status: Post['status']) => { return status === 'draft' diff --git a/examples/query/react/graphql/tsconfig.json b/examples/query/react/graphql/tsconfig.json index 2e7afa3896..6812fef180 100644 --- a/examples/query/react/graphql/tsconfig.json +++ b/examples/query/react/graphql/tsconfig.json @@ -1,20 +1,5 @@ { - "include": ["./src/**/*"], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": ["dom", "es2015"], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } + "extends": "@reduxjs/tsconfig/create-react-app", + "compilerOptions": {}, + "include": ["src"] } diff --git a/examples/query/react/infinite-queries/.eslintrc.json b/examples/query/react/infinite-queries/.eslintrc.json deleted file mode 100644 index e41a5aee79..0000000000 --- a/examples/query/react/infinite-queries/.eslintrc.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "extends": [ - "eslint:recommended", - "react-app", - "plugin:react/jsx-runtime", - "prettier" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { "project": true, "tsconfigRootDir": "./" }, - "plugins": ["@typescript-eslint"], - "root": true, - "ignorePatterns": ["dist"], - "rules": { - "@typescript-eslint/consistent-type-imports": [ - 2, - { "fixStyle": "separate-type-imports" } - ], - "@typescript-eslint/no-restricted-imports": [ - 2, - { - "paths": [ - { - "name": "react-redux", - "importNames": ["useSelector", "useStore", "useDispatch"], - "message": "Please use pre-typed versions from `src/app/hooks.ts` instead." - } - ] - } - ] - }, - "overrides": [ - { "files": ["*.{c,m,}{t,j}s", "*.{t,j}sx"] }, - { "files": ["*{test,spec}.{t,j}s?(x)"], "env": { "jest": true } } - ] -} diff --git a/examples/query/react/infinite-queries/.prettierrc.json b/examples/query/react/infinite-queries/.prettierrc.json deleted file mode 100644 index 18b9c97f02..0000000000 --- a/examples/query/react/infinite-queries/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "semi": false, - "arrowParens": "avoid" -} diff --git a/examples/query/react/infinite-queries/package.json b/examples/query/react/infinite-queries/package.json index 0644ea3adc..92979f2843 100644 --- a/examples/query/react/infinite-queries/package.json +++ b/examples/query/react/infinite-queries/package.json @@ -6,16 +6,17 @@ "scripts": { "dev": "vite", "start": "vite", - "build": "tsc && vite build", + "build": "tsc -b && vite build", "preview": "vite preview", - "test": "vitest run", - "format": "prettier --write .", - "lint": "eslint .", - "lint:fix": "eslint --fix .", - "type-check": "tsc --noEmit" + "test": "yarn run -T test", + "format-check": "yarn run -T format-check", + "format": "yarn run -T format", + "lint-fix": "yarn run -T lint-fix", + "lint": "yarn run -T lint", + "type-check": "tsc -b --noEmit" }, "dependencies": { - "@reduxjs/toolkit": "https://pkg.csb.dev/reduxjs/redux-toolkit/commit/2aca4f24/@reduxjs/toolkit/_pkg.tgz", + "@reduxjs/toolkit": "workspace:^", "react": "^18.2.0", "react-dom": "^18.2.0", "react-intersection-observer": "^9.13.1", @@ -24,24 +25,27 @@ "react-router": "^7.0.1" }, "devDependencies": { - "@testing-library/dom": "^9.3.4", - "@testing-library/jest-dom": "^6.2.0", - "@testing-library/react": "^14.1.2", - "@testing-library/user-event": "^14.5.2", - "@types/react": "18.3.12", - "@types/react-dom": "18.3.1", + "@reduxjs/eslint-config": "workspace:^", + "@reduxjs/prettier-config": "workspace:^", + "@reduxjs/tsconfig": "workspace:^", + "@reduxjs/vitest-config": "workspace:^", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^22.15.18", + "@types/react": "^19.1.4", + "@types/react-dom": "^19.1.5", "@types/react-native-web": "^0.19", "@vitejs/plugin-react": "^4.2.1", - "jsdom": "^23.2.0", + "eslint": "^9.27.0", + "jiti": "^2.4.2", + "jsdom": "^26.1.0", "msw": "^2.6.6", - "prettier": "^3.2.1", + "prettier": "^3.5.3", "typescript": "^5.8.2", - "vite": "^5.0.0", - "vitest": "^1.2.0" - }, - "resolutions": { - "@types/react": "18.3.12", - "@types/react-dom": "18.3.1" + "vite": "^6.3.5", + "vitest": "^3.1.3" }, "msw": { "workerDirectory": [ diff --git a/examples/query/react/infinite-queries/src/App.test.tsx b/examples/query/react/infinite-queries/src/App.test.tsx index 06b45be816..6dedd55ea0 100644 --- a/examples/query/react/infinite-queries/src/App.test.tsx +++ b/examples/query/react/infinite-queries/src/App.test.tsx @@ -1,105 +1,105 @@ -import { screen, waitFor } from "@testing-library/react" -import App from "./App" -import { renderWithProviders } from "./utils/test-utils" +import { screen, waitFor } from '@testing-library/react' +import App from './App' +import { renderWithProviders } from './utils/test-utils' -test("App should have correct initial render", () => { +test('App should have correct initial render', () => { renderWithProviders() // The app should be rendered correctly expect(screen.getByText(/learn/i)).toBeInTheDocument() // Initial state: count should be 0, incrementValue should be 2 - expect(screen.getByLabelText("Count")).toHaveTextContent("0") - expect(screen.getByLabelText("Set increment amount")).toHaveValue(2) + expect(screen.getByLabelText('Count')).toHaveTextContent('0') + expect(screen.getByLabelText('Set increment amount')).toHaveValue(2) }) -test("Increment value and Decrement value should work as expected", async () => { +test('Increment value and Decrement value should work as expected', async () => { const { user } = renderWithProviders() // Click on "+" => Count should be 1 - await user.click(screen.getByLabelText("Increment value")) - expect(screen.getByLabelText("Count")).toHaveTextContent("1") + await user.click(screen.getByLabelText('Increment value')) + expect(screen.getByLabelText('Count')).toHaveTextContent('1') // Click on "-" => Count should be 0 - await user.click(screen.getByLabelText("Decrement value")) - expect(screen.getByLabelText("Count")).toHaveTextContent("0") + await user.click(screen.getByLabelText('Decrement value')) + expect(screen.getByLabelText('Count')).toHaveTextContent('0') }) -test("Add Amount should work as expected", async () => { +test('Add Amount should work as expected', async () => { const { user } = renderWithProviders() // "Add Amount" button is clicked => Count should be 2 - await user.click(screen.getByText("Add Amount")) - expect(screen.getByLabelText("Count")).toHaveTextContent("2") + await user.click(screen.getByText('Add Amount')) + expect(screen.getByLabelText('Count')).toHaveTextContent('2') - const incrementValueInput = screen.getByLabelText("Set increment amount") + const incrementValueInput = screen.getByLabelText('Set increment amount') // incrementValue is 2, click on "Add Amount" => Count should be 4 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "2") - await user.click(screen.getByText("Add Amount")) - expect(screen.getByLabelText("Count")).toHaveTextContent("4") + await user.type(incrementValueInput, '2') + await user.click(screen.getByText('Add Amount')) + expect(screen.getByLabelText('Count')).toHaveTextContent('4') // [Negative number] incrementValue is -1, click on "Add Amount" => Count should be 3 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "-1") - await user.click(screen.getByText("Add Amount")) - expect(screen.getByLabelText("Count")).toHaveTextContent("3") + await user.type(incrementValueInput, '-1') + await user.click(screen.getByText('Add Amount')) + expect(screen.getByLabelText('Count')).toHaveTextContent('3') }) -it("Add Async should work as expected", async () => { +it('Add Async should work as expected', async () => { const { user } = renderWithProviders() // "Add Async" button is clicked => Count should be 2 - await user.click(screen.getByText("Add Async")) + await user.click(screen.getByText('Add Async')) await waitFor(() => - expect(screen.getByLabelText("Count")).toHaveTextContent("2"), + expect(screen.getByLabelText('Count')).toHaveTextContent('2'), ) - const incrementValueInput = screen.getByLabelText("Set increment amount") + const incrementValueInput = screen.getByLabelText('Set increment amount') // incrementValue is 2, click on "Add Async" => Count should be 4 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "2") + await user.type(incrementValueInput, '2') - await user.click(screen.getByText("Add Async")) + await user.click(screen.getByText('Add Async')) await waitFor(() => - expect(screen.getByLabelText("Count")).toHaveTextContent("4"), + expect(screen.getByLabelText('Count')).toHaveTextContent('4'), ) // [Negative number] incrementValue is -1, click on "Add Async" => Count should be 3 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "-1") - await user.click(screen.getByText("Add Async")) + await user.type(incrementValueInput, '-1') + await user.click(screen.getByText('Add Async')) await waitFor(() => - expect(screen.getByLabelText("Count")).toHaveTextContent("3"), + expect(screen.getByLabelText('Count')).toHaveTextContent('3'), ) }) -test("Add If Odd should work as expected", async () => { +test('Add If Odd should work as expected', async () => { const { user } = renderWithProviders() // "Add If Odd" button is clicked => Count should stay 0 - await user.click(screen.getByText("Add If Odd")) - expect(screen.getByLabelText("Count")).toHaveTextContent("0") + await user.click(screen.getByText('Add If Odd')) + expect(screen.getByLabelText('Count')).toHaveTextContent('0') // Click on "+" => Count should be updated to 1 - await user.click(screen.getByLabelText("Increment value")) - expect(screen.getByLabelText("Count")).toHaveTextContent("1") + await user.click(screen.getByLabelText('Increment value')) + expect(screen.getByLabelText('Count')).toHaveTextContent('1') // "Add If Odd" button is clicked => Count should be updated to 3 - await user.click(screen.getByText("Add If Odd")) - expect(screen.getByLabelText("Count")).toHaveTextContent("3") + await user.click(screen.getByText('Add If Odd')) + expect(screen.getByLabelText('Count')).toHaveTextContent('3') - const incrementValueInput = screen.getByLabelText("Set increment amount") + const incrementValueInput = screen.getByLabelText('Set increment amount') // incrementValue is 1, click on "Add If Odd" => Count should be updated to 4 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "1") - await user.click(screen.getByText("Add If Odd")) - expect(screen.getByLabelText("Count")).toHaveTextContent("4") + await user.type(incrementValueInput, '1') + await user.click(screen.getByText('Add If Odd')) + expect(screen.getByLabelText('Count')).toHaveTextContent('4') // click on "Add If Odd" => Count should stay 4 await user.clear(incrementValueInput) - await user.type(incrementValueInput, "-1") - await user.click(screen.getByText("Add If Odd")) - expect(screen.getByLabelText("Count")).toHaveTextContent("4") + await user.type(incrementValueInput, '-1') + await user.click(screen.getByText('Add If Odd')) + expect(screen.getByLabelText('Count')).toHaveTextContent('4') }) diff --git a/examples/query/react/infinite-queries/src/App.tsx b/examples/query/react/infinite-queries/src/App.tsx index 77f4b56ff1..fad0401e9f 100644 --- a/examples/query/react/infinite-queries/src/App.tsx +++ b/examples/query/react/infinite-queries/src/App.tsx @@ -1,17 +1,17 @@ -import { BrowserRouter, Link, Route, Routes, useLocation } from "react-router" -import "./App.css" +import { BrowserRouter, Link, Route, Routes, useLocation } from 'react-router' +import './App.css' -import { Outlet } from "react-router" -import BidirectionalCursorInfScroll from "./features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll" +import { Outlet } from 'react-router' +import BidirectionalCursorInfScroll from './features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll' import { InfiniteScrollAbout, InfiniteScrollExample, -} from "./features/infinite-scroll/InfiniteScrollExample" -import LimitOffsetExample from "./features/limit-offset/LimitOffsetExample" -import { InfiniteScrollMaxPagesExample } from "./features/max-pages/InfiniteScrollMaxExample" -import PaginationInfScrollExample from "./features/pagination-infinite-scroll/PaginationInfScrollExample" -import { PaginationExample } from "./features/pagination/PaginationExample" -import { FlatlistExample } from "./features/rn-flatlist/FlatlistExample" +} from './features/infinite-scroll/InfiniteScrollExample' +import LimitOffsetExample from './features/limit-offset/LimitOffsetExample' +import { InfiniteScrollMaxPagesExample } from './features/max-pages/InfiniteScrollMaxExample' +import PaginationInfScrollExample from './features/pagination-infinite-scroll/PaginationInfScrollExample' +import { PaginationExample } from './features/pagination/PaginationExample' +import { FlatlistExample } from './features/rn-flatlist/FlatlistExample' const Menu = () => { return ( diff --git a/examples/query/react/infinite-queries/src/app/createAppSlice.ts b/examples/query/react/infinite-queries/src/app/createAppSlice.ts index 64afebbb60..7f0601350d 100644 --- a/examples/query/react/infinite-queries/src/app/createAppSlice.ts +++ b/examples/query/react/infinite-queries/src/app/createAppSlice.ts @@ -1,4 +1,4 @@ -import { asyncThunkCreator, buildCreateSlice } from "@reduxjs/toolkit" +import { asyncThunkCreator, buildCreateSlice } from '@reduxjs/toolkit' // `buildCreateSlice` allows us to create a slice with async thunks. export const createAppSlice = buildCreateSlice({ diff --git a/examples/query/react/infinite-queries/src/app/hooks.ts b/examples/query/react/infinite-queries/src/app/hooks.ts index bc8990df57..2706f2c627 100644 --- a/examples/query/react/infinite-queries/src/app/hooks.ts +++ b/examples/query/react/infinite-queries/src/app/hooks.ts @@ -3,9 +3,9 @@ // usage of typed hooks throughout the application. // We disable the ESLint rule here because this is the designated place // for importing and re-exporting the typed versions of hooks. -/* eslint-disable @typescript-eslint/no-restricted-imports */ -import { useDispatch, useSelector } from "react-redux" -import type { AppDispatch, RootState } from "./store" + +import { useDispatch, useSelector } from 'react-redux' +import type { AppDispatch, RootState } from './store' // Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch = useDispatch.withTypes() diff --git a/examples/query/react/infinite-queries/src/app/store.ts b/examples/query/react/infinite-queries/src/app/store.ts index f71a782819..743509b72e 100644 --- a/examples/query/react/infinite-queries/src/app/store.ts +++ b/examples/query/react/infinite-queries/src/app/store.ts @@ -1,7 +1,7 @@ -import type { Action, ThunkAction } from "@reduxjs/toolkit" -import { combineSlices, configureStore } from "@reduxjs/toolkit" -import { setupListeners } from "@reduxjs/toolkit/query" -import { baseApi } from "../features/baseApi" +import type { Action, ThunkAction } from '@reduxjs/toolkit' +import { combineSlices, configureStore } from '@reduxjs/toolkit' +import { setupListeners } from '@reduxjs/toolkit/query' +import { baseApi } from '../features/baseApi' // `combineSlices` automatically combines the reducers using // their `reducerPath`s, therefore we no longer need to call `combineReducers`. @@ -16,7 +16,7 @@ export const makeStore = (preloadedState?: Partial) => { reducer: rootReducer, // Adding the api middleware enables caching, invalidation, polling, // and other useful features of `rtk-query`. - middleware: getDefaultMiddleware => { + middleware: (getDefaultMiddleware) => { return getDefaultMiddleware().concat(baseApi.middleware) }, preloadedState, @@ -32,7 +32,7 @@ export const store = makeStore() // Infer the type of `store` export type AppStore = typeof store // Infer the `AppDispatch` type from the store itself -export type AppDispatch = AppStore["dispatch"] +export type AppDispatch = AppStore['dispatch'] export type AppThunk = ThunkAction< ThunkReturnType, RootState, diff --git a/examples/query/react/infinite-queries/src/app/useIntersectionCallback.ts b/examples/query/react/infinite-queries/src/app/useIntersectionCallback.ts index 63834f0cef..f17c6aba50 100644 --- a/examples/query/react/infinite-queries/src/app/useIntersectionCallback.ts +++ b/examples/query/react/infinite-queries/src/app/useIntersectionCallback.ts @@ -1,4 +1,4 @@ -import { useCallback, useRef } from "react" +import { useCallback, useRef } from 'react' export function useIntersectionCallback(onIntersectCallback: () => void) { const intersectionObserverRef = useRef(null) @@ -9,7 +9,7 @@ export function useIntersectionCallback(onIntersectCallback: () => void) { intersectionObserverRef.current.disconnect() } - intersectionObserverRef.current = new IntersectionObserver(entries => { + intersectionObserverRef.current = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { onIntersectCallback() } diff --git a/examples/query/react/infinite-queries/src/features/baseApi.ts b/examples/query/react/infinite-queries/src/features/baseApi.ts index 9f460f1a8c..5147293039 100644 --- a/examples/query/react/infinite-queries/src/features/baseApi.ts +++ b/examples/query/react/infinite-queries/src/features/baseApi.ts @@ -1,6 +1,6 @@ -import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react" +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' export const baseApi = createApi({ - baseQuery: fetchBaseQuery({ baseUrl: "/" }), - endpoints: build => ({}), + baseQuery: fetchBaseQuery({ baseUrl: '/' }), + endpoints: (build) => ({}), }) diff --git a/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll.tsx b/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll.tsx index 5011057290..21c9fb73e5 100644 --- a/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll.tsx +++ b/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/BidirectionalCursorInfScroll.tsx @@ -1,7 +1,7 @@ -import React, { useCallback, useEffect, useRef, useState } from "react" -import { Link, useLocation } from "react-router" -import { useIntersectionCallback } from "../../app/useIntersectionCallback" -import { apiWithInfiniteScroll } from "./infiniteScrollApi" +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { Link, useLocation } from 'react-router' +import { useIntersectionCallback } from '../../app/useIntersectionCallback' +import { apiWithInfiniteScroll } from './infiniteScrollApi' const limit = 10 @@ -42,8 +42,8 @@ function BidirectionalCursorInfScroll({ startingProject = { id: 25 } }) { const startingElement = startingProjectRef.current if (startingElement) { startingElement.scrollIntoView({ - behavior: "auto", - block: "center", + behavior: 'auto', + block: 'center', }) setHasCentered(true) } @@ -64,30 +64,30 @@ function BidirectionalCursorInfScroll({ startingProject = { id: 25 } }) { disabled={!hasPreviousPage || isFetchingPreviousPage} > {isFetchingPreviousPage - ? "Loading more..." + ? 'Loading more...' : hasPreviousPage - ? "Load Older" - : "Nothing more to load"} + ? 'Load Older' + : 'Nothing more to load'}
- {data?.pages.map(page => ( + {data?.pages.map((page) => ( {page.projects.map((project, index, arr) => { return (
{isFetchingNextPage - ? "Loading more..." + ? 'Loading more...' : hasNextPage - ? "Load Newer" - : "Nothing more to load"} + ? 'Load Newer' + : 'Nothing more to load'}
{isFetching && !isFetchingPreviousPage && !isFetchingNextPage - ? "Background Updating..." + ? 'Background Updating...' : null}
diff --git a/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/infiniteScrollApi.ts b/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/infiniteScrollApi.ts index dc4b68ddab..44ed0fbbd7 100644 --- a/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/infiniteScrollApi.ts +++ b/examples/query/react/infinite-queries/src/features/bidirectional-cursor-infinite-scroll/infiniteScrollApi.ts @@ -1,4 +1,4 @@ -import { baseApi } from "../baseApi" +import { baseApi } from '../baseApi' type Project = { id: number @@ -25,7 +25,7 @@ type ProjectsInitialPageParam = { type QueryParamLimit = number export const apiWithInfiniteScroll = baseApi.injectEndpoints({ - endpoints: build => ({ + endpoints: (build) => ({ getProjectsBidirectionalCursor: build.infiniteQuery< ProjectsCursorPaginated, QueryParamLimit, @@ -33,13 +33,13 @@ export const apiWithInfiniteScroll = baseApi.injectEndpoints({ >({ query: ({ pageParam: { before, after, around, limit } }) => { const params = new URLSearchParams() - params.append("limit", String(limit)) + params.append('limit', String(limit)) if (after != null) { - params.append("after", String(after)) + params.append('after', String(after)) } else if (before != null) { - params.append("before", String(before)) + params.append('before', String(before)) } else if (around != null) { - params.append("around", String(around)) + params.append('around', String(around)) } return { diff --git a/examples/query/react/infinite-queries/src/features/infinite-scroll/InfiniteScrollExample.tsx b/examples/query/react/infinite-queries/src/features/infinite-scroll/InfiniteScrollExample.tsx index e8b738a255..10adfa2a71 100644 --- a/examples/query/react/infinite-queries/src/features/infinite-scroll/InfiniteScrollExample.tsx +++ b/examples/query/react/infinite-queries/src/features/infinite-scroll/InfiniteScrollExample.tsx @@ -1,15 +1,15 @@ -import React from "react" -import { useInView } from "react-intersection-observer" -import { Link } from "react-router" +import React from 'react' +import { useInView } from 'react-intersection-observer' +import { Link } from 'react-router' -import { apiWithInfiniteScroll } from "./infiniteScrollApi" -import type { Project } from "./infiniteScrollApi" +import { apiWithInfiniteScroll } from './infiniteScrollApi' +import type { Project } from './infiniteScrollApi' export const InfiniteScrollAbout = () => { return ( { + onClick={(e) => { window.history.back() e.preventDefault() }} @@ -23,9 +23,9 @@ export const ProjectRow = ({ project }: { project: Project }) => { return (

{ isError, } = apiWithInfiniteScroll.endpoints.getProjectsCursor.useInfiniteQuery( - "projects", + 'projects', ) const { ref, inView } = useInView() React.useEffect(() => { if (inView) { - console.log("Fetching next page") + console.log('Fetching next page') fetchNextPage() } }, [fetchNextPage, inView]) @@ -81,9 +81,9 @@ export const InfiniteScrollExample = () => { : "Nothing more to load"} */}

- {data?.pages.map(page => ( + {data?.pages.map((page) => ( - {page.projects.map(project => ( + {page.projects.map((project) => ( ))} @@ -95,13 +95,13 @@ export const InfiniteScrollExample = () => { disabled={!hasNextPage || isFetchingNextPage} > {isFetchingNextPage - ? "Loading more..." + ? 'Loading more...' : hasNextPage - ? "Load Newer" - : "Nothing more to load"} + ? 'Load Newer' + : 'Nothing more to load'}
-
{isFetching ? "Background Updating..." : null}
+
{isFetching ? 'Background Updating...' : null}
}
diff --git a/examples/query/react/infinite-queries/src/features/infinite-scroll/infiniteScrollApi.ts b/examples/query/react/infinite-queries/src/features/infinite-scroll/infiniteScrollApi.ts index c543d44f1d..7317fa6c03 100644 --- a/examples/query/react/infinite-queries/src/features/infinite-scroll/infiniteScrollApi.ts +++ b/examples/query/react/infinite-queries/src/features/infinite-scroll/infiniteScrollApi.ts @@ -1,4 +1,4 @@ -import { baseApi } from "../baseApi" +import { baseApi } from '../baseApi' export type Project = { id: number @@ -12,13 +12,13 @@ type ProjectsPageCursor = { } export const apiWithInfiniteScroll = baseApi.injectEndpoints({ - endpoints: build => ({ + endpoints: (build) => ({ getProjectsCursor: build.infiniteQuery({ query: ({ pageParam }) => `https://example.com/api/projectsCursor?cursor=${pageParam}`, infiniteQueryOptions: { initialPageParam: 0, - getPreviousPageParam: firstPage => firstPage.previousId, + getPreviousPageParam: (firstPage) => firstPage.previousId, getNextPageParam: ( lastPage, allPages, diff --git a/examples/query/react/infinite-queries/src/features/limit-offset/LimitOffsetExample.tsx b/examples/query/react/infinite-queries/src/features/limit-offset/LimitOffsetExample.tsx index 9610879fb2..cf421784cb 100644 --- a/examples/query/react/infinite-queries/src/features/limit-offset/LimitOffsetExample.tsx +++ b/examples/query/react/infinite-queries/src/features/limit-offset/LimitOffsetExample.tsx @@ -1,11 +1,12 @@ -import { createSelector } from "@reduxjs/toolkit" -import { +import { createSelector } from '@reduxjs/toolkit' +import type { BaseQueryFn, TypedUseQueryStateResult, -} from "@reduxjs/toolkit/query/react" -import { Link, useLocation } from "react-router" -import { useIntersectionCallback } from "../../app/useIntersectionCallback" -import { apiWithInfiniteScroll, ProjectsResponse } from "./infiniteScrollApi" +} from '@reduxjs/toolkit/query/react' +import { Link, useLocation } from 'react-router' +import { useIntersectionCallback } from '../../app/useIntersectionCallback' +import type { ProjectsResponse } from './infiniteScrollApi' +import { apiWithInfiniteScroll } from './infiniteScrollApi' type ProjectsInfiniteQueryResult = TypedUseQueryStateResult< { pages: ProjectsResponse[] }, @@ -17,7 +18,7 @@ const selectCombinedProjects = createSelector( (res: ProjectsInfiniteQueryResult) => { return res.data }, - data => data?.pages?.map(item => item?.projects)?.flat(), + (data) => data?.pages?.map((item) => item?.projects)?.flat(), ) function LimitOffsetExample() { @@ -37,7 +38,7 @@ function LimitOffsetExample() { } = apiWithInfiniteScroll.endpoints.projectsLimitOffset.useInfiniteQuery( undefined, { - selectFromResult: result => { + selectFromResult: (result) => { return { ...result, combinedData: selectCombinedProjects(result), @@ -65,27 +66,27 @@ function LimitOffsetExample() { disabled={!hasPreviousPage || isFetchingPreviousPage} > {isFetchingPreviousPage - ? "Loading more..." + ? 'Loading more...' : hasPreviousPage - ? "Load Older" - : "Nothing more to load"} + ? 'Load Older' + : 'Nothing more to load'}
{combinedData?.map((project, index, arr) => { return (
{isFetchingNextPage - ? "Loading more..." + ? 'Loading more...' : hasNextPage - ? "Load Newer" - : "Nothing more to load"} + ? 'Load Newer' + : 'Nothing more to load'}
{isFetching && !isFetchingPreviousPage && !isFetchingNextPage - ? "Background Updating..." + ? 'Background Updating...' : null}
diff --git a/examples/query/react/infinite-queries/src/features/limit-offset/infiniteScrollApi.ts b/examples/query/react/infinite-queries/src/features/limit-offset/infiniteScrollApi.ts index 97aae393e5..e4458dfb9c 100644 --- a/examples/query/react/infinite-queries/src/features/limit-offset/infiniteScrollApi.ts +++ b/examples/query/react/infinite-queries/src/features/limit-offset/infiniteScrollApi.ts @@ -1,4 +1,4 @@ -import { baseApi } from "../baseApi" +import { baseApi } from '../baseApi' type Project = { id: number @@ -17,7 +17,7 @@ type ProjectsInitialPageParam = { } export const apiWithInfiniteScroll = baseApi.injectEndpoints({ - endpoints: build => ({ + endpoints: (build) => ({ projectsLimitOffset: build.infiniteQuery< ProjectsResponse, void, diff --git a/examples/query/react/infinite-queries/src/features/max-pages/InfiniteScrollMaxExample.tsx b/examples/query/react/infinite-queries/src/features/max-pages/InfiniteScrollMaxExample.tsx index f91c47e0e3..947afd8fa6 100644 --- a/examples/query/react/infinite-queries/src/features/max-pages/InfiniteScrollMaxExample.tsx +++ b/examples/query/react/infinite-queries/src/features/max-pages/InfiniteScrollMaxExample.tsx @@ -1,5 +1,5 @@ -import React from "react" -import { apiWithInfiniteScrollMax } from "./infiniteScrollApi" +import React from 'react' +import { apiWithInfiniteScrollMax } from './infiniteScrollApi' export const InfiniteScrollMaxPagesExample = () => { const { @@ -13,7 +13,7 @@ export const InfiniteScrollMaxPagesExample = () => { isError, } = apiWithInfiniteScrollMax.endpoints.getProjectsCursorMax.useInfiniteQuery( - "projects", + 'projects', ) // TODO This should be built in to RTKQ @@ -38,19 +38,19 @@ export const InfiniteScrollMaxPagesExample = () => { { /*isFetchingPreviousPage ? 'Loading more...' - :*/ hasPreviousPage ? "Load Older" : "Nothing more to load" + :*/ hasPreviousPage ? 'Load Older' : 'Nothing more to load' }
- {data?.pages.map(page => ( + {data?.pages.map((page) => ( - {page.projects.map(project => ( + {page.projects.map((project) => (

{ disabled={!hasNextPage /* || isFetchingNextPage*/} > {isFetchingNextPage - ? "Loading more..." + ? 'Loading more...' : hasNextPage - ? "Load Newer" - : "Nothing more to load"} + ? 'Load Newer' + : 'Nothing more to load'}

{isFetching && !isFetchingNextPage - ? "Background Updating..." + ? 'Background Updating...' : null}
diff --git a/examples/query/react/infinite-queries/src/features/max-pages/infiniteScrollApi.ts b/examples/query/react/infinite-queries/src/features/max-pages/infiniteScrollApi.ts index 3a6247ea10..a891478f6e 100644 --- a/examples/query/react/infinite-queries/src/features/max-pages/infiniteScrollApi.ts +++ b/examples/query/react/infinite-queries/src/features/max-pages/infiniteScrollApi.ts @@ -1,4 +1,4 @@ -import { baseApi } from "../baseApi" +import { baseApi } from '../baseApi' type Project = { id: number @@ -12,7 +12,7 @@ type ProjectsPageCursor = { } export const apiWithInfiniteScrollMax = baseApi.injectEndpoints({ - endpoints: build => ({ + endpoints: (build) => ({ getProjectsCursorMax: build.infiniteQuery< ProjectsPageCursor, string, @@ -23,8 +23,8 @@ export const apiWithInfiniteScrollMax = baseApi.injectEndpoints({ infiniteQueryOptions: { initialPageParam: 0, maxPages: 3, - getPreviousPageParam: firstPage => firstPage.previousId ?? undefined, - getNextPageParam: lastPage => lastPage.nextId ?? undefined, + getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined, + getNextPageParam: (lastPage) => lastPage.nextId ?? undefined, }, }), }), diff --git a/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/PaginationInfScrollExample.tsx b/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/PaginationInfScrollExample.tsx index c461b0a09c..36a6ba8227 100644 --- a/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/PaginationInfScrollExample.tsx +++ b/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/PaginationInfScrollExample.tsx @@ -1,11 +1,12 @@ -import { createSelector } from "@reduxjs/toolkit" -import { +import { createSelector } from '@reduxjs/toolkit' +import type { BaseQueryFn, TypedUseQueryStateResult, -} from "@reduxjs/toolkit/query/react" -import { Link, useLocation } from "react-router" -import { useIntersectionCallback } from "../../app/useIntersectionCallback" -import { apiWithInfiniteScroll, ProjectsResponse } from "./infiniteScrollApi" +} from '@reduxjs/toolkit/query/react' +import { Link, useLocation } from 'react-router' +import { useIntersectionCallback } from '../../app/useIntersectionCallback' +import type { ProjectsResponse } from './infiniteScrollApi' +import { apiWithInfiniteScroll } from './infiniteScrollApi' type ProjectsInfiniteQueryResult = TypedUseQueryStateResult< { pages: ProjectsResponse[] }, @@ -17,7 +18,7 @@ const selectCombinedProjects = createSelector( (res: ProjectsInfiniteQueryResult) => { return res.data }, - data => data?.pages?.map(item => item?.projects)?.flat(), + (data) => data?.pages?.map((item) => item?.projects)?.flat(), ) function PaginationInfScrollExample() { @@ -37,7 +38,7 @@ function PaginationInfScrollExample() { } = apiWithInfiniteScroll.endpoints.projectsPaginated.useInfiniteQuery( undefined, { - selectFromResult: result => { + selectFromResult: (result) => { return { ...result, combinedData: selectCombinedProjects(result), @@ -65,27 +66,27 @@ function PaginationInfScrollExample() { disabled={!hasPreviousPage || isFetchingPreviousPage} > {isFetchingPreviousPage - ? "Loading more..." + ? 'Loading more...' : hasPreviousPage - ? "Load Older" - : "Nothing more to load"} + ? 'Load Older' + : 'Nothing more to load'}
{combinedData?.map((project, index, arr) => { return (
{isFetchingNextPage - ? "Loading more..." + ? 'Loading more...' : hasNextPage - ? "Load Newer" - : "Nothing more to load"} + ? 'Load Newer' + : 'Nothing more to load'}
{isFetching && !isFetchingPreviousPage && !isFetchingNextPage - ? "Background Updating..." + ? 'Background Updating...' : null}
diff --git a/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/infiniteScrollApi.ts b/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/infiniteScrollApi.ts index eaa463f169..549891dde4 100644 --- a/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/infiniteScrollApi.ts +++ b/examples/query/react/infinite-queries/src/features/pagination-infinite-scroll/infiniteScrollApi.ts @@ -1,4 +1,4 @@ -import { baseApi } from "../baseApi" +import { baseApi } from '../baseApi' type Project = { id: number @@ -17,7 +17,7 @@ interface ProjectsInitialPageParam { } export const apiWithInfiniteScroll = baseApi.injectEndpoints({ - endpoints: build => ({ + endpoints: (build) => ({ projectsPaginated: build.infiniteQuery< ProjectsResponse, void, @@ -64,7 +64,7 @@ export const apiWithInfiniteScroll = baseApi.injectEndpoints({ query: ({ pageParam: { page, size } }) => { return { url: `https://example.com/api/projectsPaginated?page=${page}&size=${size}`, - method: "GET", + method: 'GET', } }, }), diff --git a/examples/query/react/infinite-queries/src/features/pagination/PaginationExample.tsx b/examples/query/react/infinite-queries/src/features/pagination/PaginationExample.tsx index d0c46fd68a..3e4bd887f0 100644 --- a/examples/query/react/infinite-queries/src/features/pagination/PaginationExample.tsx +++ b/examples/query/react/infinite-queries/src/features/pagination/PaginationExample.tsx @@ -1,5 +1,5 @@ -import React from "react" -import { apiWithPagination } from "./paginationApi" +import React from 'react' +import { apiWithPagination } from './paginationApi' // The React Query example actually just uses a normal query // rather than an infinite query, and Dominik confirmed that @@ -19,7 +19,7 @@ export const PaginationExample = () => { isFetchingNextPage, isFetching, isError, - } = apiWithPagination.endpoints.getProjects.useInfiniteQuery("projects") + } = apiWithPagination.endpoints.getProjects.useInfiniteQuery('projects') const currentPage = data?.pages[page] @@ -29,15 +29,15 @@ export const PaginationExample = () => {
Current Page: {page + 1}
{" "} + {' '}