diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json deleted file mode 100644 index 75bde4e176..0000000000 --- a/.codesandbox/ci.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "installCommand": "install:csb", - "buildCommand": "build:csb", - "sandboxes": [ - "/examples/angular/basic", - "/examples/react/basic-typescript", - "/examples/solid/basic-typescript", - "/examples/svelte/basic", - "/examples/vue/basic" - ], - "packages": ["packages/**"], - "node": "18" -} diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index e9bfccb9d0..0000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,142 +0,0 @@ -// @ts-check - -/** @type {import('eslint').Linter.Config} */ -const config = { - root: true, - reportUnusedDisableDirectives: true, - ignorePatterns: ['**/build', '**/coverage', '**/dist'], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'import'], - extends: [ - 'eslint:recommended', - 'plugin:@cspell/recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/stylistic', - 'plugin:import/recommended', - 'plugin:import/typescript', - 'prettier', - ], - env: { - browser: true, - es2020: true, - }, - parserOptions: { - tsconfigRootDir: __dirname, - project: true, - sourceType: 'module', - ecmaVersion: 2020, - }, - settings: { - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - 'import/resolver': { - typescript: true, - }, - react: { - version: 'detect', - }, - }, - rules: { - '@cspell/spellchecker': [ - 'error', - { - cspell: { - words: [ - 'tanstack', // Our package scope - 'tsqd', // Our public interface (TanStack Query Devtools shorthand) - 'retryer', // Our public interface - 'Promisable', // Our public interface - 'extralight', // Our public interface - 'codemod', // We support our codemod - 'typecheck', // Field of vite.config.ts - 'TSES', // @typescript-eslint package's interface - 'tsup', // We use tsup as builder - 'solidjs', // Our target framework - 'tabular-nums', // https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric - 'todos', // Too general word to be caught as error - 'vue-demi', // dependency of @tanstack/vue-query - ], - }, - }, - ], - '@typescript-eslint/array-type': [ - 'error', - { default: 'generic', readonly: 'generic' }, - ], - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/consistent-type-definitions': 'off', - '@typescript-eslint/consistent-type-imports': [ - 'error', - { prefer: 'type-imports' }, - ], - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/method-signature-style': ['error', 'property'], - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'typeParameter', - format: ['PascalCase'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - custom: { - regex: '^(T|T[A-Z][A-Za-z]+)$', - match: true, - }, - }, - ], - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/no-empty-interface': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-unnecessary-condition': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-inferrable-types': [ - 'error', - { ignoreParameters: true }, - ], - 'import/default': 'off', - 'import/export': 'off', - 'import/namespace': 'off', - 'import/newline-after-import': 'error', - 'import/no-cycle': 'error', - 'import/no-duplicates': 'off', - 'import/no-named-as-default-member': 'off', - 'import/no-unresolved': ['error', { ignore: ['^@tanstack/'] }], - 'import/no-unused-modules': ['off', { unusedExports: true }], - 'import/order': [ - 'error', - { - groups: [ - 'builtin', - 'external', - 'internal', - 'parent', - 'sibling', - 'index', - 'object', - 'type', - ], - }, - ], - 'no-case-declarations': 'off', - 'no-empty': 'off', - 'no-prototype-builtins': 'off', - 'no-redeclare': 'off', - 'no-shadow': 'error', - 'no-undef': 'off', - 'sort-imports': ['error', { ignoreDeclarationSort: true }], - }, - overrides: [ - { - files: ['**/*.test.{ts,tsx}'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, - ], -} - -module.exports = config diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000000..52f722aca2 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "configMigration": true, + "extends": [ + "config:recommended", + "group:allNonMajor", + "schedule:weekly", + ":approveMajorUpdates", + ":automergeMinor", + ":disablePeerDependencies", + ":maintainLockFilesMonthly", + ":semanticCommits", + ":semanticCommitTypeAll(chore)" + ], + "ignorePresets": [":ignoreModulesAndTests"], + "labels": ["dependencies"], + "rangeStrategy": "bump", + "postUpdateOptions": ["pnpmDedupe"], + "ignoreDeps": [ + "@types/node", + "@types/react", + "@types/react-dom", + "eslint-plugin-react-compiler", + "node", + "react", + "react-dom", + "react-scripts", + "tsup", + "typescript", + "typescript47", + "typescript48", + "typescript49", + "typescript50", + "typescript51", + "typescript52", + "vue", + "vue-tsc", + "vue2", + "vue2.7" + ] +} diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml new file mode 100644 index 0000000000..f44bcff450 --- /dev/null +++ b/.github/workflows/autofix.yml @@ -0,0 +1,29 @@ +name: autofix.ci # needed to securely identify the workflow + +on: + pull_request: + push: + branches: [main, alpha, beta, rc, v4] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + autofix: + name: autofix + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.1.7 + - name: Setup Tools + uses: tanstack/config/.github/setup@main + - name: Fix formatting + run: pnpm prettier:write + - name: Apply fixes + uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c + with: + commit-message: 'ci: apply automated fixes' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5c7422825..41f9886be3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: description: override release tag required: false push: - branches: ['main', 'alpha', 'beta', 'rc', 'v4'] + branches: [main, alpha, beta, rc, v4] concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.ref }} @@ -16,29 +16,24 @@ concurrency: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} +permissions: + contents: write + id-token: write + jobs: test-and-publish: name: Test & Publish - if: github.repository == 'TanStack/query' + if: github.repository_owner == 'TanStack' runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: '0' - - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: actions/checkout@v4.1.7 with: - version: 8 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - cache: pnpm + fetch-depth: 0 - name: Start Nx Agents run: npx nx-cloud start-ci-run --distribute-on=".nx/workflows/dynamic-changesets.yaml" - - name: Install dependencies - run: pnpm install --frozen-lockfile --prefer-offline + - name: Setup Tools + uses: tanstack/config/.github/setup@main - name: Run Tests run: pnpm run test:ci --parallel=3 - name: Stop Nx Agents @@ -51,12 +46,12 @@ jobs: npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" pnpm run cipublish env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} TAG: ${{ inputs.tag }} - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v4.5.0 with: directory: packages + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index c28106ae50..a271cb7e68 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -7,6 +7,6 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@v4.3.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 8eb4ac7f60..734e4a0168 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -2,8 +2,8 @@ name: pr on: pull_request: - paths-ignore: - - 'media/**' + push: + branches: ['svelte-5-adapter'] concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.ref }} @@ -12,38 +12,48 @@ concurrency: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} +permissions: + contents: read + jobs: - main: - name: Nx Cloud - Main Job + test: + name: Test runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v4.1.7 with: fetch-depth: 0 - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - cache: pnpm - name: Start Nx Agents run: npx nx-cloud start-ci-run --distribute-on=".nx/workflows/dynamic-changesets.yaml" - - name: Install dependencies - run: pnpm install --frozen-lockfile --prefer-offline + - name: Setup Tools + uses: tanstack/config/.github/setup@main - name: Get base and head commits for `nx affected` - uses: nrwl/nx-set-shas@v3 + uses: nrwl/nx-set-shas@v4.0.6 with: - main-branch-name: 'main' - - name: Run Tests + main-branch-name: main + - name: Run Checks run: pnpm run test:pr --parallel=3 - name: Stop Nx Agents if: ${{ always() }} run: npx nx-cloud stop-all-agents - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v4.5.0 with: directory: packages + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + preview: + name: Preview + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + - name: Setup Tools + uses: tanstack/config/.github/setup@main + - name: Build Packages + run: pnpm run build:all + - name: Publish Previews + run: pnpx pkg-pr-new publish --pnpm --compact './packages/*' --template './examples/*/*' diff --git a/.gitignore b/.gitignore index 5c90883e87..9ad1f8224b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ stats.html .cache .idea .nx/cache +.nx/workspace-data .pnpm-store .svelte-kit .tsup diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index cb2c84d5c3..0000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1 +0,0 @@ -pnpm lint-staged diff --git a/.lintstagedrc b/.lintstagedrc deleted file mode 100644 index 0111deae6a..0000000000 --- a/.lintstagedrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "*": ["prettier --write"] -} diff --git a/.npmrc b/.npmrc index 2eb0732302..84aee8d998 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,3 @@ +link-workspace-packages=true prefer-workspace-packages=true +provenance=true diff --git a/.nvmrc b/.nvmrc index eb800ed459..58a1f0907f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18.19.0 +22.4.0 diff --git a/.nx/workflows/dynamic-changesets.yaml b/.nx/workflows/dynamic-changesets.yaml index 29c58231b2..d3536f3ba7 100644 --- a/.nx/workflows/dynamic-changesets.yaml +++ b/.nx/workflows/dynamic-changesets.yaml @@ -1,4 +1,4 @@ distribute-on: - small-changeset: 8 linux-medium-js - medium-changeset: 10 linux-medium-js - large-changeset: 12 linux-medium-js + small-changeset: 3 linux-medium-js + medium-changeset: 6 linux-medium-js + large-changeset: 10 linux-medium-js diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs new file mode 100644 index 0000000000..1bc0c19d30 --- /dev/null +++ b/.pnpmfile.cjs @@ -0,0 +1,42 @@ +function readPackage(pkg, context) { + // react-scripts@4.0.3 + if (pkg.name === 'react-scripts' && pkg.version === '4.0.3') { + delete pkg.dependencies['@typescript-eslint/eslint-plugin'] + delete pkg.dependencies['@typescript-eslint/parser'] + delete pkg.dependencies['babel-eslint'] + delete pkg.dependencies['babel-jest'] + delete pkg.dependencies['eslint'] + delete pkg.dependencies['eslint-config-react-app'] + delete pkg.dependencies['eslint-plugin-flowtype'] + delete pkg.dependencies['eslint-plugin-import'] + delete pkg.dependencies['eslint-plugin-jest'] + delete pkg.dependencies['eslint-plugin-jsx-a11y'] + delete pkg.dependencies['eslint-plugin-react'] + delete pkg.dependencies['eslint-plugin-react-hooks'] + delete pkg.dependencies['eslint-plugin-testing-library'] + delete pkg.dependencies['jest'] + delete pkg.dependencies['jest-circus'] + delete pkg.dependencies['jest-resolve'] + delete pkg.dependencies['jest-watch-typeahead'] + context.log('Removed unused dependencies from react-scripts@4.0.3') + } + + // react-scripts@5.0.1 + if (pkg.name === 'react-scripts' && pkg.version === '5.0.1') { + delete pkg.dependencies['babel-jest'] + delete pkg.dependencies['eslint'] + delete pkg.dependencies['eslint-config-react-app'] + delete pkg.dependencies['jest'] + delete pkg.dependencies['jest-resolve'] + delete pkg.dependencies['jest-watch-typeahead'] + context.log('Removed unused dependencies from react-scripts@5.0.1') + } + + return pkg +} + +module.exports = { + hooks: { + readPackage, + }, +} diff --git a/.prettierignore b/.prettierignore index 0d948ff1e5..928bbaada5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,3 +8,6 @@ pnpm-lock.yaml packages/**/tsup.config.bundled*.mjs **/tsconfig.vitest-temp.json + +# API Extractor report +packages/angular-query-experimental/etc/*.md diff --git a/codecov.yml b/codecov.yml index 23b5e9f34b..2fb73fb3da 100644 --- a/codecov.yml +++ b/codecov.yml @@ -2,11 +2,17 @@ coverage: status: project: default: - target: 90% + target: auto threshold: 1% + base: auto comment: layout: 'header, reach, diff, flags, components' + behavior: default + require_changes: false + require_base: false + require_head: true + hide_project_coverage: false component_management: individual_components: diff --git a/docs/config.json b/docs/config.json index 01ddf6e8fe..24239e85e6 100644 --- a/docs/config.json +++ b/docs/config.json @@ -144,6 +144,10 @@ { "label": "Devtools", "to": "framework/angular/devtools" + }, + { + "label": "Zoneless", + "to": "framework/angular/zoneless" } ] } @@ -325,6 +329,10 @@ "label": "Query Functions", "to": "framework/vue/guides/query-functions" }, + { + "label": "Query Options", + "to": "framework/vue/guides/query-options" + }, { "label": "Network Mode", "to": "framework/vue/guides/network-mode" @@ -369,10 +377,6 @@ "label": "Placeholder Query Data", "to": "framework/vue/guides/placeholder-query-data" }, - { - "label": "Prefetching", - "to": "framework/vue/guides/prefetching" - }, { "label": "Mutations", "to": "framework/vue/guides/mutations" @@ -386,7 +390,7 @@ "to": "framework/vue/guides/invalidations-from-mutations" }, { - "label": "Updates from Mutation", + "label": "Updates from Mutation Responses", "to": "framework/vue/guides/updates-from-mutation-responses" }, { @@ -405,6 +409,10 @@ "label": "Filters", "to": "framework/vue/guides/filters" }, + { + "label": "Prefetching", + "to": "framework/vue/guides/prefetching" + }, { "label": "SSR & Nuxt", "to": "framework/vue/guides/ssr" @@ -650,6 +658,14 @@ "label": "infiniteQueryOptions", "to": "framework/react/reference/infiniteQueryOptions" }, + { + "label": "usePrefetchQuery", + "to": "framework/react/reference/usePrefetchQuery" + }, + { + "label": "usePrefetchInfiniteQuery", + "to": "framework/react/reference/usePrefetchInfiniteQuery" + }, { "label": "QueryErrorResetBoundary", "to": "framework/react/reference/QueryErrorResetBoundary" @@ -691,10 +707,22 @@ "label": "useIsMutating", "to": "framework/vue/reference/useIsMutating" }, + { + "label": "useMutationState", + "to": "framework/vue/reference/useMutationState" + }, { "label": "useQueryClient", "to": "framework/vue/reference/useQueryClient" }, + { + "label": "queryOptions", + "to": "framework/vue/reference/queryOptions" + }, + { + "label": "infiniteQueryOptions", + "to": "framework/vue/reference/infiniteQueryOptions" + }, { "label": "hydration", "to": "framework/vue/reference/hydration" @@ -709,6 +737,40 @@ "to": "framework/solid/reference/createQuery" } ] + }, + { + "label": "svelte", + "children": [ + { + "label": "Svelte Reference", + "to": "framework/svelte/reference/index" + }, + { + "label": "Functions / createQuery", + "to": "framework/svelte/reference/functions/createquery" + }, + { + "label": "Functions / createMutation", + "to": "framework/svelte/reference/functions/createmutation" + } + ] + }, + { + "label": "angular", + "children": [ + { + "label": "Angular Reference", + "to": "framework/angular/reference/index" + }, + { + "label": "Functions / injectQuery", + "to": "framework/angular/reference/functions/injectquery" + }, + { + "label": "Functions / injectMutation", + "to": "framework/angular/reference/functions/injectmutation" + } + ] } ] }, @@ -758,8 +820,8 @@ "to": "framework/vue/community/tkdodos-blog" }, { - "label": "Query Key Factory", - "to": "framework/vue/community/lukemorales-query-key-factory" + "label": "Community Projects", + "to": "framework/vue/community/community-projects" } ] } @@ -833,9 +895,13 @@ "to": "framework/react/examples/rick-morty" }, { - "label": "Next.js", + "label": "Next.js Pages", "to": "framework/react/examples/nextjs" }, + { + "label": "Next.js app with prefetching", + "to": "framework/react/examples/nextjs-app-prefetching" + }, { "label": "Next.js app with streaming", "to": "framework/react/examples/nextjs-suspense-streaming" @@ -871,7 +937,7 @@ }, { "label": "Basic", - "to": "framework/solid/examples/basic-typescript" + "to": "framework/solid/examples/basic" }, { "label": "Basic w/ GraphQL-Request", @@ -932,8 +998,8 @@ "to": "framework/svelte/examples/ssr" }, { - "label": "Optimistic Updates in TypeScript", - "to": "framework/svelte/examples/optimistic-updates-typescript" + "label": "Optimistic Updates", + "to": "framework/svelte/examples/optimistic-updates" }, { "label": "Playground", @@ -1000,6 +1066,19 @@ "to": "framework/react/plugins/createPersister" } ] + }, + { + "label": "vue", + "children": [ + { + "label": "broadcastQueryClient (Experimental)", + "to": "framework/vue/plugins/broadcastQueryClient" + }, + { + "label": "createPersister (Experimental)", + "to": "framework/vue/plugins/createPersister" + } + ] } ] } diff --git a/docs/eslint/eslint-plugin-query.md b/docs/eslint/eslint-plugin-query.md index 661943b8b9..23da9cd354 100644 --- a/docs/eslint/eslint-plugin-query.md +++ b/docs/eslint/eslint-plugin-query.md @@ -19,34 +19,68 @@ $ yarn add -D @tanstack/eslint-plugin-query $ bun add -D @tanstack/eslint-plugin-query ``` -## Usage +## Flat Config (`eslint.config.js`) -To enable all of the recommended rules for our plugin, add `plugin:@tanstack/eslint-plugin-query/recommended` in extends: +### Recommended setup -```json -{ - "extends": ["plugin:@tanstack/eslint-plugin-query/recommended"] -} +To enable all of the recommended rules for our plugin, add the following config: + +```js +import pluginQuery from '@tanstack/eslint-plugin-query' + +export default [ + ...pluginQuery.configs['flat/recommended'], + // Any other config... +] +``` + +### Custom setup + +Alternatively, you can load the plugin and configure only the rules you want to use: + +```js +import pluginQuery from '@tanstack/eslint-plugin-query' + +export default [ + { + plugins: { + '@tanstack/query': pluginQuery, + }, + rules: { + '@tanstack/query/exhaustive-deps': 'error', + }, + }, + // Any other config... +] ``` -### Alternative config +## Legacy Config (`.eslintrc`) -Alternatively, add `@tanstack/eslint-plugin-query` to the plugins section of your `.eslintrc` configuration file: +### Recommended setup + +To enable all of the recommended rules for our plugin, add `plugin:@tanstack/eslint-plugin-query/recommended` in extends: ```json { - "plugins": ["@tanstack/query"] + "extends": ["plugin:@tanstack/eslint-plugin-query/recommended"] } ``` -Then configure the rules you want to use under the rules section: +### Custom setup + +Alternatively, add `@tanstack/eslint-plugin-query` to the plugins section, and configure the rules you want to use: ```json { + "plugins": ["@tanstack/query"], "rules": { - "@tanstack/query/exhaustive-deps": "error", - "@tanstack/query/no-rest-destructuring": "warn", - "@tanstack/query/stable-query-client": "error" + "@tanstack/query/exhaustive-deps": "error" } } ``` + +## Rules + +- [@tanstack/query/exhaustive-deps](../exhaustive-deps) +- [@tanstack/query/no-rest-destructuring](../no-rest-destructuring) +- [@tanstack/query/stable-query-client](../stable-query-client) diff --git a/docs/framework/angular/devtools.md b/docs/framework/angular/devtools.md index b2d8e3c836..394522855d 100644 --- a/docs/framework/angular/devtools.md +++ b/docs/framework/angular/devtools.md @@ -29,7 +29,7 @@ Floating Mode will mount the devtools as a fixed, floating element in your app a Place the following code as high in your Angular app as you can. The closer it is to the root of the page, the better it will work! -```ts +```angular-ts import { AngularQueryDevtools } from '@tanstack/angular-query-devtools-experimental' import { Component } from '@angular/core'; diff --git a/docs/framework/angular/guides/background-fetching-indicators.md b/docs/framework/angular/guides/background-fetching-indicators.md index cae36e009d..5ad6ee3ef4 100644 --- a/docs/framework/angular/guides/background-fetching-indicators.md +++ b/docs/framework/angular/guides/background-fetching-indicators.md @@ -6,7 +6,7 @@ ref: docs/framework/react/guides/background-fetching-indicators.md [//]: # 'Example' -```ts +```angular-ts @Component({ selector: 'posts', template: ` @@ -39,7 +39,7 @@ export class TodosComponent { [//]: # 'Example' [//]: # 'Example2' -```ts +```angular-ts import { injectIsFetching } from '@tanstack/angular-query-experimental' @Component({ diff --git a/docs/framework/angular/guides/disabling-queries.md b/docs/framework/angular/guides/disabling-queries.md index 39b5408586..a57ac39728 100644 --- a/docs/framework/angular/guides/disabling-queries.md +++ b/docs/framework/angular/guides/disabling-queries.md @@ -7,7 +7,7 @@ replace: { 'useQuery': 'injectQuery' } [//]: # 'Example' -```ts +```angular-ts @Component({ selector: 'todos', template: `
@@ -44,7 +44,7 @@ export class TodosComponent { [//]: # 'Example' [//]: # 'Example2' -```ts +```angular-ts @Component({ selector: 'todos', template: ` @@ -69,7 +69,7 @@ export class TodosComponent { [//]: # 'Example2' [//]: # 'Example3' -```ts +```angular-ts @Component({ selector: 'todos', template: ` diff --git a/docs/framework/angular/guides/infinite-queries.md b/docs/framework/angular/guides/infinite-queries.md index d299142600..9fdde83e26 100644 --- a/docs/framework/angular/guides/infinite-queries.md +++ b/docs/framework/angular/guides/infinite-queries.md @@ -8,7 +8,7 @@ replace: [//]: # 'Example' -```ts +```angular-ts import { Component, computed, inject } from '@angular/core' import { injectInfiniteQuery } from '@tanstack/angular-query-experimental' import { lastValueFrom } from 'rxjs' @@ -48,7 +48,7 @@ export class Example { } ``` -```html +```angular-html
@if (query.isPending()) {

Loading...

@@ -70,7 +70,7 @@ export class Example { [//]: # 'Example' [//]: # 'Example1' -```ts +```angular-ts @Component({ template: ` `, }) diff --git a/docs/framework/angular/guides/mutations.md b/docs/framework/angular/guides/mutations.md index b8adc4d039..5ba756d625 100644 --- a/docs/framework/angular/guides/mutations.md +++ b/docs/framework/angular/guides/mutations.md @@ -14,7 +14,7 @@ replace: [//]: # 'Example' -```ts +```angular-ts @Component({ template: `
@@ -45,7 +45,7 @@ export class TodosComponent { [//]: # 'Example2' [//]: # 'Example3' -```ts +```angular-ts @Component({ standalone: true, selector: 'todo-item', diff --git a/docs/framework/angular/guides/optimistic-updates.md b/docs/framework/angular/guides/optimistic-updates.md index 4786759124..08c6931516 100644 --- a/docs/framework/angular/guides/optimistic-updates.md +++ b/docs/framework/angular/guides/optimistic-updates.md @@ -28,7 +28,7 @@ addTodo = injectMutation(() => ({ [//]: # 'ExampleUI1' [//]: # 'ExampleUI2' -```ts +```angular-ts @Component({ template: ` @for (todo of todos.data(); track todo.id) { @@ -45,7 +45,7 @@ class TodosComponent {} [//]: # 'ExampleUI2' [//]: # 'ExampleUI3' -```ts +```angular-ts @Component({ template: ` @if (addTodo.isError()) { diff --git a/docs/framework/angular/guides/paginated-queries.md b/docs/framework/angular/guides/paginated-queries.md index 5dbb4ffcae..3fe42c6a9a 100644 --- a/docs/framework/angular/guides/paginated-queries.md +++ b/docs/framework/angular/guides/paginated-queries.md @@ -22,7 +22,7 @@ const result = injectQuery(() => ({ [//]: # 'Example' [//]: # 'Example2' -```ts +```angular-ts @Component({ selector: 'pagination-example', template: ` diff --git a/docs/framework/angular/guides/queries.md b/docs/framework/angular/guides/queries.md index 88898c13bf..3aa9b75853 100644 --- a/docs/framework/angular/guides/queries.md +++ b/docs/framework/angular/guides/queries.md @@ -33,7 +33,7 @@ result = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList })) [//]: # 'Example2' [//]: # 'Example3' -```ts +```angular-ts @Component({ selector: 'todos', standalone: true, @@ -66,7 +66,7 @@ If booleans aren't your thing, you can always use the `status` state as well: [//]: # 'Example4' -```ts +```angular-ts @Component({ selector: 'todos', standalone: true, diff --git a/docs/framework/angular/guides/query-cancellation.md b/docs/framework/angular/guides/query-cancellation.md index b2884d7255..7699625aad 100644 --- a/docs/framework/angular/guides/query-cancellation.md +++ b/docs/framework/angular/guides/query-cancellation.md @@ -81,7 +81,7 @@ You might want to cancel a query manually. For example, if the request takes a l [//]: # 'Example7' -```ts +```angular-ts @Component({ standalone: true, template: ``, diff --git a/docs/framework/angular/installation.md b/docs/framework/angular/installation.md index cd18b9256f..877f4cf089 100644 --- a/docs/framework/angular/installation.md +++ b/docs/framework/angular/installation.md @@ -10,13 +10,13 @@ title: Installation _Angular Query is compatible with Angular v16 and higher_ ```bash -$ npm i @tanstack/angular-query-experimental +npm i @tanstack/angular-query-experimental # or -$ pnpm add @tanstack/angular-query-experimental +pnpm add @tanstack/angular-query-experimental # or -$ yarn add @tanstack/angular-query-experimental +yarn add @tanstack/angular-query-experimental # or -$ bun add @tanstack/angular-query-experimental +bun add @tanstack/angular-query-experimental ``` > Wanna give it a spin before you download? Try out the [simple](../examples/simple) or [basic](../examples/basic) examples! diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index 1eb2882124..06aa5e89f9 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -60,7 +60,7 @@ In the example below, you can see Angular Query in its most basic and simple for [Open in CodeSandbox](https://codesandbox.io/s/github/tanstack/query/tree/main/examples/angular/simple) -```ts +```angular-ts import { AngularQueryDevtools } from '@tanstack/angular-query-devtools-experimental' import { ChangeDetectionStrategy, Component, inject } from '@angular/core' import { HttpClient } from '@angular/common/http' diff --git a/docs/framework/angular/quick-start.md b/docs/framework/angular/quick-start.md index ff3c29ae6b..f82b85322e 100644 --- a/docs/framework/angular/quick-start.md +++ b/docs/framework/angular/quick-start.md @@ -43,7 +43,7 @@ export class AppModule {} ### Component with query and mutation -```ts +```angular-ts import { Component, Injectable, inject } from '@angular/core' import { HttpClient } from '@angular/common/http' import { lastValueFrom } from 'rxjs' diff --git a/docs/framework/angular/reference/functions/infinitequeryoptions.md b/docs/framework/angular/reference/functions/infinitequeryoptions.md new file mode 100644 index 0000000000..9d76ed9456 --- /dev/null +++ b/docs/framework/angular/reference/functions/infinitequeryoptions.md @@ -0,0 +1,132 @@ +--- +id: infiniteQueryOptions +title: infiniteQueryOptions +--- + +# Function: infiniteQueryOptions() + +Allows to share and re-use infinite query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +## Param + +The infinite query options to tag with the type from `queryFn`. + +## infiniteQueryOptions(options) + +```ts +function infiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>( + options, +): UndefinedInitialDataInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam +> & + object +``` + +Allows to share and re-use infinite query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +### Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +### Parameters + +• **options**: [`UndefinedInitialDataInfiniteOptions`](../type-aliases/undefinedinitialdatainfiniteoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> + +The infinite query options to tag with the type from `queryFn`. + +### Returns + +[`UndefinedInitialDataInfiniteOptions`](../type-aliases/undefinedinitialdatainfiniteoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` + +The tagged infinite query options. + +The tagged infinite query options. + +### Param + +The infinite query options to tag with the type from `queryFn`. + +### Defined in + +[infinite-query-options.ts:59](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/infinite-query-options.ts#L59) + +## infiniteQueryOptions(options) + +```ts +function infiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>( + options, +): DefinedInitialDataInfiniteOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam +> & + object +``` + +Allows to share and re-use infinite query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +### Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +### Parameters + +• **options**: [`DefinedInitialDataInfiniteOptions`](../type-aliases/definedinitialdatainfiniteoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> + +The infinite query options to tag with the type from `queryFn`. + +### Returns + +[`DefinedInitialDataInfiniteOptions`](../type-aliases/definedinitialdatainfiniteoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> & `object` + +The tagged infinite query options. + +The tagged infinite query options. + +### Param + +The infinite query options to tag with the type from `queryFn`. + +### Defined in + +[infinite-query-options.ts:91](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/infinite-query-options.ts#L91) diff --git a/docs/framework/angular/reference/functions/injectinfinitequery.md b/docs/framework/angular/reference/functions/injectinfinitequery.md new file mode 100644 index 0000000000..225f71d041 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectinfinitequery.md @@ -0,0 +1,188 @@ +--- +id: injectInfiniteQuery +title: injectInfiniteQuery +--- + +# Function: injectInfiniteQuery() + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or "infinite scroll" + +## Param + +A function that returns infinite query options. + +## Param + +The Angular injector to use. + +## injectInfiniteQuery(optionsFn, injector) + +```ts +function injectInfiniteQuery< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>(optionsFn, injector?): CreateInfiniteQueryResult +``` + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or "infinite scroll" + +### Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +### Parameters + +• **optionsFn** + +A function that returns infinite query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`CreateInfiniteQueryResult`](../type-aliases/createinfinitequeryresult.md)\<`TData`, `TError`\> + +The infinite query result. + +The infinite query result. + +### Param + +A function that returns infinite query options. + +### Param + +The Angular injector to use. + +### Defined in + +[inject-infinite-query.ts:30](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-infinite-query.ts#L30) + +## injectInfiniteQuery(optionsFn, injector) + +```ts +function injectInfiniteQuery< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>(optionsFn, injector?): DefinedCreateInfiniteQueryResult +``` + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or "infinite scroll" + +### Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +### Parameters + +• **optionsFn** + +A function that returns infinite query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`DefinedCreateInfiniteQueryResult`](../type-aliases/definedcreateinfinitequeryresult.md)\<`TData`, `TError`\> + +The infinite query result. + +The infinite query result. + +### Param + +A function that returns infinite query options. + +### Param + +The Angular injector to use. + +### Defined in + +[inject-infinite-query.ts:57](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-infinite-query.ts#L57) + +## injectInfiniteQuery(optionsFn, injector) + +```ts +function injectInfiniteQuery< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>(optionsFn, injector?): CreateInfiniteQueryResult +``` + +Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +Infinite queries can additively "load more" data onto an existing set of data or "infinite scroll" + +### Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +### Parameters + +• **optionsFn** + +A function that returns infinite query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`CreateInfiniteQueryResult`](../type-aliases/createinfinitequeryresult.md)\<`TData`, `TError`\> + +The infinite query result. + +The infinite query result. + +### Param + +A function that returns infinite query options. + +### Param + +The Angular injector to use. + +### Defined in + +[inject-infinite-query.ts:84](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-infinite-query.ts#L84) diff --git a/docs/framework/angular/reference/functions/injectisfetching.md b/docs/framework/angular/reference/functions/injectisfetching.md new file mode 100644 index 0000000000..79a7335ba3 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectisfetching.md @@ -0,0 +1,35 @@ +--- +id: injectIsFetching +title: injectIsFetching +--- + +# Function: injectIsFetching() + +```ts +function injectIsFetching(filters?, injector?): Signal +``` + +Injects a signal that tracks the number of queries that your application is loading or +fetching in the background. + +Can be used for app-wide loading indicators + +## Parameters + +• **filters?**: `QueryFilters` + +The filters to apply to the query. + +• **injector?**: `Injector` + +The Angular injector to use. + +## Returns + +`Signal`\<`number`\> + +signal with number of loading or fetching queries. + +## Defined in + +[inject-is-fetching.ts:17](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-is-fetching.ts#L17) diff --git a/docs/framework/angular/reference/functions/injectismutating.md b/docs/framework/angular/reference/functions/injectismutating.md new file mode 100644 index 0000000000..210fdf4d56 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectismutating.md @@ -0,0 +1,34 @@ +--- +id: injectIsMutating +title: injectIsMutating +--- + +# Function: injectIsMutating() + +```ts +function injectIsMutating(filters?, injector?): Signal +``` + +Injects a signal that tracks the number of mutations that your application is fetching. + +Can be used for app-wide loading indicators + +## Parameters + +• **filters?**: `MutationFilters` + +The filters to apply to the query. + +• **injector?**: `Injector` + +The Angular injector to use. + +## Returns + +`Signal`\<`number`\> + +signal with number of fetching mutations. + +## Defined in + +[inject-is-mutating.ts:16](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-is-mutating.ts#L16) diff --git a/docs/framework/angular/reference/functions/injectmutation.md b/docs/framework/angular/reference/functions/injectmutation.md new file mode 100644 index 0000000000..f649b79e96 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectmutation.md @@ -0,0 +1,47 @@ +--- +id: injectMutation +title: injectMutation +--- + +# Function: injectMutation() + +```ts +function injectMutation( + optionsFn, + injector?, +): CreateMutationResult +``` + +Injects a mutation: an imperative function that can be invoked which typically performs server side effects. + +Unlike queries, mutations are not run automatically. + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `Error` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Parameters + +• **optionsFn** + +A function that returns mutation options. + +• **injector?**: `Injector` + +The Angular injector to use. + +## Returns + +[`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`\> + +The mutation. + +## Defined in + +[inject-mutation.ts:38](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-mutation.ts#L38) diff --git a/docs/framework/angular/reference/functions/injectmutationstate.md b/docs/framework/angular/reference/functions/injectmutationstate.md new file mode 100644 index 0000000000..899067a3c6 --- /dev/null +++ b/docs/framework/angular/reference/functions/injectmutationstate.md @@ -0,0 +1,39 @@ +--- +id: injectMutationState +title: injectMutationState +--- + +# Function: injectMutationState() + +```ts +function injectMutationState( + mutationStateOptionsFn, + options?, +): Signal +``` + +Injects a signal that tracks the state of all mutations. + +## Type Parameters + +• **TResult** = `MutationState`\<`unknown`, `Error`, `unknown`, `unknown`\> + +## Parameters + +• **mutationStateOptionsFn** = `...` + +A function that returns mutation state options. + +• **options?**: [`InjectMutationStateOptions`](../interfaces/injectmutationstateoptions.md) + +The Angular injector to use. + +## Returns + +`Signal`\<`TResult`[]\> + +The signal that tracks the state of all mutations. + +## Defined in + +[inject-mutation-state.ts:53](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-mutation-state.ts#L53) diff --git a/docs/framework/angular/reference/functions/injectqueries.md b/docs/framework/angular/reference/functions/injectqueries.md new file mode 100644 index 0000000000..89403c640d --- /dev/null +++ b/docs/framework/angular/reference/functions/injectqueries.md @@ -0,0 +1,37 @@ +--- +id: injectQueries +title: injectQueries +--- + +# Function: injectQueries() + +```ts +function injectQueries( + __namedParameters, + injector?, +): Signal +``` + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TCombinedResult** = `T` _extends_ [] ? [] : `T` _extends_ [`Head`] ? [`GetResults`\<`Head`\>] : `T` _extends_ [`Head`, `...Tail[]`] ? [`...Tail[]`] _extends_ [] ? [] : [`...Tail[]`] _extends_ [`Head`] ? [`GetResults`\<`Head`\>, `GetResults`\<`Head`\>] : [`...Tail[]`] _extends_ [`Head`, `...Tail[]`] ? [`...Tail[]`] _extends_ [] ? [] : [`...Tail[]`] _extends_ [`Head`] ? [`GetResults`\<`Head`\>, `GetResults`\<`Head`\>, `GetResults`\<`Head`\>] : [`...Tail[]`] _extends_ [`Head`, `...Tail[]`] ? [`...(...)[]`] _extends_ [] ? [] : ... _extends_ ... ? ... : ... : [`...(...)[]`] _extends_ ...[] ? ...[] : ...[] : [`...Tail[]`] _extends_ `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `any`\>[] ? `QueryObserverResult`\<`unknown` _extends_ `TData` ? `TQueryFnData` : `TData`, `unknown` _extends_ `TError` ? `Error` : `TError`\>[] : `QueryObserverResult`[] : `T` _extends_ `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `any`\>[] ? `QueryObserverResult`\<`unknown` _extends_ `TData` ? `TQueryFnData` : `TData`, `unknown` _extends_ `TError` ? `Error` : `TError`\>[] : `QueryObserverResult`[] + +## Parameters + +• **\_\_namedParameters** + +• **\_\_namedParameters.combine?** + +• **\_\_namedParameters.queries?**: `Signal`\<[`...(T extends [] ? [] : T extends [Head] ? [GetOptions] : T extends [Head, ...Tail[]] ? [...Tail[]] extends [] ? [] : [...Tail[]] extends [Head] ? [GetOptions, GetOptions] : [...Tail[]] extends [Head, ...Tail[]] ? [...(...)[]] extends [] ? [] : (...) extends (...) ? (...) : (...) : readonly (...)[] extends [...(...)[]] ? [...(...)[]] : (...) extends (...) ? (...) : (...) : readonly unknown[] extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[])[]`]\> + +• **injector?**: `Injector` + +## Returns + +`Signal`\<`TCombinedResult`\> + +## Defined in + +[inject-queries.ts:188](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-queries.ts#L188) diff --git a/docs/framework/angular/reference/functions/injectquery.md b/docs/framework/angular/reference/functions/injectquery.md new file mode 100644 index 0000000000..aa0b3196bf --- /dev/null +++ b/docs/framework/angular/reference/functions/injectquery.md @@ -0,0 +1,321 @@ +--- +id: injectQuery +title: injectQuery +--- + +# Function: injectQuery() + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + +**Basic example** + +```ts +class ServiceOrComponent { + query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + this.#http.get('https://api.github.com/repos/tanstack/query'), + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. +In the example below, the query will be automatically enabled and executed when the filter signal changes +to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. + +**Reactive example** + +```ts +class ServiceOrComponent { + filter = signal('') + + todosQuery = injectQuery(() => ({ + queryKey: ['todos', this.filter()], + queryFn: () => fetchTodos(this.filter()), + // Signals can be combined with expressions + enabled: !!this.filter(), + })) +} +``` + +## Param + +A function that returns query options. + +## Param + +The Angular injector to use. + +## See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +## injectQuery(optionsFn, injector) + +```ts +function injectQuery( + optionsFn, + injector?, +): DefinedCreateQueryResult +``` + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + +**Basic example** + +```ts +class ServiceOrComponent { + query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + this.#http.get('https://api.github.com/repos/tanstack/query'), + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. +In the example below, the query will be automatically enabled and executed when the filter signal changes +to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. + +**Reactive example** + +```ts +class ServiceOrComponent { + filter = signal('') + + todosQuery = injectQuery(() => ({ + queryKey: ['todos', this.filter()], + queryFn: () => fetchTodos(this.filter()), + // Signals can be combined with expressions + enabled: !!this.filter(), + })) +} +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **optionsFn** + +A function that returns query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`DefinedCreateQueryResult`](../type-aliases/definedcreatequeryresult.md)\<`TData`, `TError`\> + +The query result. + +The query result. + +### Param + +A function that returns query options. + +### Param + +The Angular injector to use. + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### Defined in + +[inject-query.ts:53](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query.ts#L53) + +## injectQuery(optionsFn, injector) + +```ts +function injectQuery( + optionsFn, + injector?, +): CreateQueryResult +``` + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + +**Basic example** + +```ts +class ServiceOrComponent { + query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + this.#http.get('https://api.github.com/repos/tanstack/query'), + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. +In the example below, the query will be automatically enabled and executed when the filter signal changes +to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. + +**Reactive example** + +```ts +class ServiceOrComponent { + filter = signal('') + + todosQuery = injectQuery(() => ({ + queryKey: ['todos', this.filter()], + queryFn: () => fetchTodos(this.filter()), + // Signals can be combined with expressions + enabled: !!this.filter(), + })) +} +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **optionsFn** + +A function that returns query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`CreateQueryResult`](../type-aliases/createqueryresult.md)\<`TData`, `TError`\> + +The query result. + +The query result. + +### Param + +A function that returns query options. + +### Param + +The Angular injector to use. + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### Defined in + +[inject-query.ts:102](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query.ts#L102) + +## injectQuery(optionsFn, injector) + +```ts +function injectQuery( + optionsFn, + injector?, +): CreateQueryResult +``` + +Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + +**Basic example** + +```ts +class ServiceOrComponent { + query = injectQuery(() => ({ + queryKey: ['repoData'], + queryFn: () => + this.#http.get('https://api.github.com/repos/tanstack/query'), + })) +} +``` + +Similar to `computed` from Angular, the function passed to `injectQuery` will be run in the reactive context. +In the example below, the query will be automatically enabled and executed when the filter signal changes +to a truthy value. When the filter signal changes back to a falsy value, the query will be disabled. + +**Reactive example** + +```ts +class ServiceOrComponent { + filter = signal('') + + todosQuery = injectQuery(() => ({ + queryKey: ['todos', this.filter()], + queryFn: () => fetchTodos(this.filter()), + // Signals can be combined with expressions + enabled: !!this.filter(), + })) +} +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **optionsFn** + +A function that returns query options. + +• **injector?**: `Injector` + +The Angular injector to use. + +### Returns + +[`CreateQueryResult`](../type-aliases/createqueryresult.md)\<`TData`, `TError`\> + +The query result. + +The query result. + +### Param + +A function that returns query options. + +### Param + +The Angular injector to use. + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### See + +https://tanstack.com/query/latest/docs/framework/angular/guides/queries + +### Defined in + +[inject-query.ts:151](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query.ts#L151) diff --git a/docs/framework/angular/reference/functions/injectqueryclient.md b/docs/framework/angular/reference/functions/injectqueryclient.md new file mode 100644 index 0000000000..ebe9bc821c --- /dev/null +++ b/docs/framework/angular/reference/functions/injectqueryclient.md @@ -0,0 +1,88 @@ +--- +id: injectQueryClient +title: injectQueryClient +--- + +# Function: injectQueryClient() + +Injects the `QueryClient` instance into the component or service. + +**Example** + +```ts +const queryClient = injectQueryClient() +``` + +## injectQueryClient() + +```ts +function injectQueryClient(): QueryClient +``` + +Injects the `QueryClient` instance into the component or service. + +**Example** + +```ts +const queryClient = injectQueryClient() +``` + +### Returns + +`QueryClient` + +### Defined in + +[inject-query-client.ts:16](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query-client.ts#L16) + +## injectQueryClient(injectOptions) + +```ts +function injectQueryClient(injectOptions): QueryClient +``` + +Injects the `QueryClient` instance into the component or service. + +**Example** + +```ts +const queryClient = injectQueryClient() +``` + +### Parameters + +• **injectOptions**: `InjectOptions` & `object` & `object` + +### Returns + +`QueryClient` + +### Defined in + +[inject-query-client.ts:16](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query-client.ts#L16) + +## injectQueryClient(injectOptions) + +```ts +function injectQueryClient(injectOptions): null | QueryClient +``` + +Injects the `QueryClient` instance into the component or service. + +**Example** + +```ts +const queryClient = injectQueryClient() +``` + +### Parameters + +• **injectOptions**: `InjectOptions` & `object` + +### Returns + +`null` \| `QueryClient` + +### Defined in + +[inject-query-client.ts:16](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query-client.ts#L16) diff --git a/docs/framework/angular/reference/functions/provideangularquery.md b/docs/framework/angular/reference/functions/provideangularquery.md new file mode 100644 index 0000000000..f6d84bb926 --- /dev/null +++ b/docs/framework/angular/reference/functions/provideangularquery.md @@ -0,0 +1,64 @@ +--- +id: provideAngularQuery +title: provideAngularQuery +--- + +# Function: provideAngularQuery() + +```ts +function provideAngularQuery(queryClient): EnvironmentProviders +``` + +Sets up providers necessary to enable TanStack Query functionality for Angular applications. + +Allows to configure a `QueryClient`. + +**Example - standalone** + +```ts +import { + provideAngularQuery, + QueryClient, +} from '@tanstack/angular-query-experimental' + +bootstrapApplication(AppComponent, { + providers: [provideAngularQuery(new QueryClient())], +}) +``` + +**Example - NgModule-based** + +```ts +import { + provideAngularQuery, + QueryClient, +} from '@tanstack/angular-query-experimental' + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule], + providers: [provideAngularQuery(new QueryClient())], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +## Parameters + +• **queryClient**: `QueryClient` + +A `QueryClient` instance. + +## Returns + +`EnvironmentProviders` + +A set of providers to set up TanStack Query. + +## See + +https://tanstack.com/query/v5/docs/framework/angular/quick-start + +## Defined in + +[providers.ts:50](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/providers.ts#L50) diff --git a/docs/framework/angular/reference/functions/providequeryclient.md b/docs/framework/angular/reference/functions/providequeryclient.md new file mode 100644 index 0000000000..b7de8ecb87 --- /dev/null +++ b/docs/framework/angular/reference/functions/providequeryclient.md @@ -0,0 +1,27 @@ +--- +id: provideQueryClient +title: provideQueryClient +--- + +# Function: provideQueryClient() + +```ts +function provideQueryClient(value): Provider +``` + +Usually [provideAngularQuery](provideangularquery.md) is used once to set up TanStack Query and the +[https://tanstack.com/query/latest/docs/reference/QueryClient|QueryClient](https://tanstack.com/query/latest/docs/reference/QueryClient|QueryClient) +for the entire application. You can use `provideQueryClient` to provide a +different `QueryClient` instance for a part of the application. + +## Parameters + +• **value**: `QueryClient` \| () => `QueryClient` + +## Returns + +`Provider` + +## Defined in + +[inject-query-client.ts:25](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-query-client.ts#L25) diff --git a/docs/framework/angular/reference/functions/queryoptions.md b/docs/framework/angular/reference/functions/queryoptions.md new file mode 100644 index 0000000000..05f9cc0a10 --- /dev/null +++ b/docs/framework/angular/reference/functions/queryoptions.md @@ -0,0 +1,144 @@ +--- +id: queryOptions +title: queryOptions +--- + +# Function: queryOptions() + +Allows to share and re-use query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +**Example** + +```ts +const { queryKey } = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(5), + // ^? Promise +}) + +const queryClient = new QueryClient() +const data = queryClient.getQueryData(queryKey) +// ^? number | undefined +``` + +## Param + +The query options to tag with the type from `queryFn`. + +## queryOptions(options) + +```ts +function queryOptions( + options, +): UndefinedInitialDataOptions & object +``` + +Allows to share and re-use query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +**Example** + +```ts +const { queryKey } = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(5), + // ^? Promise +}) + +const queryClient = new QueryClient() +const data = queryClient.getQueryData(queryKey) +// ^? number | undefined +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`UndefinedInitialDataOptions`](../type-aliases/undefinedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +The query options to tag with the type from `queryFn`. + +### Returns + +[`UndefinedInitialDataOptions`](../type-aliases/undefinedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` + +The tagged query options. + +The tagged query options. + +### Param + +The query options to tag with the type from `queryFn`. + +### Defined in + +[query-options.ts:52](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/query-options.ts#L52) + +## queryOptions(options) + +```ts +function queryOptions( + options, +): DefinedInitialDataOptions & object +``` + +Allows to share and re-use query options in a type-safe way. + +The `queryKey` will be tagged with the type from `queryFn`. + +**Example** + +```ts +const { queryKey } = queryOptions({ + queryKey: ['key'], + queryFn: () => Promise.resolve(5), + // ^? Promise +}) + +const queryClient = new QueryClient() +const data = queryClient.getQueryData(queryKey) +// ^? number | undefined +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`DefinedInitialDataOptions`](../type-aliases/definedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +The query options to tag with the type from `queryFn`. + +### Returns + +[`DefinedInitialDataOptions`](../type-aliases/definedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` + +The tagged query options. + +The tagged query options. + +### Param + +The query options to tag with the type from `queryFn`. + +### Defined in + +[query-options.ts:85](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/query-options.ts#L85) diff --git a/docs/framework/angular/reference/index.md b/docs/framework/angular/reference/index.md new file mode 100644 index 0000000000..a0f861def3 --- /dev/null +++ b/docs/framework/angular/reference/index.md @@ -0,0 +1,50 @@ +--- +id: '@tanstack/angular-query-experimental' +title: '@tanstack/angular-query-experimental' +--- + +# @tanstack/angular-query-experimental + +## Interfaces + +- [BaseMutationNarrowing](interfaces/basemutationnarrowing.md) +- [BaseQueryNarrowing](interfaces/basequerynarrowing.md) +- [CreateBaseQueryOptions](interfaces/createbasequeryoptions.md) +- [CreateInfiniteQueryOptions](interfaces/createinfinitequeryoptions.md) +- [CreateMutationOptions](interfaces/createmutationoptions.md) +- [CreateQueryOptions](interfaces/createqueryoptions.md) +- [InjectMutationStateOptions](interfaces/injectmutationstateoptions.md) + +## Type Aliases + +- [CreateBaseMutationResult](type-aliases/createbasemutationresult.md) +- [CreateBaseQueryResult](type-aliases/createbasequeryresult.md) +- [CreateInfiniteQueryResult](type-aliases/createinfinitequeryresult.md) +- [CreateMutateAsyncFunction](type-aliases/createmutateasyncfunction.md) +- [CreateMutateFunction](type-aliases/createmutatefunction.md) +- [CreateMutationResult](type-aliases/createmutationresult.md) +- [CreateQueryResult](type-aliases/createqueryresult.md) +- [DefinedCreateInfiniteQueryResult](type-aliases/definedcreateinfinitequeryresult.md) +- [DefinedCreateQueryResult](type-aliases/definedcreatequeryresult.md) +- [DefinedInitialDataInfiniteOptions](type-aliases/definedinitialdatainfiniteoptions.md) +- [DefinedInitialDataOptions](type-aliases/definedinitialdataoptions.md) +- [NonUndefinedGuard](type-aliases/nonundefinedguard.md) +- [QueriesOptions](type-aliases/queriesoptions.md) +- [QueriesResults](type-aliases/queriesresults.md) +- [UndefinedInitialDataInfiniteOptions](type-aliases/undefinedinitialdatainfiniteoptions.md) +- [UndefinedInitialDataOptions](type-aliases/undefinedinitialdataoptions.md) + +## Functions + +- [infiniteQueryOptions](functions/infinitequeryoptions.md) +- [injectInfiniteQuery](functions/injectinfinitequery.md) +- [injectIsFetching](functions/injectisfetching.md) +- [injectIsMutating](functions/injectismutating.md) +- [injectMutation](functions/injectmutation.md) +- [injectMutationState](functions/injectmutationstate.md) +- [injectQueries](functions/injectqueries.md) +- [injectQuery](functions/injectquery.md) +- [injectQueryClient](functions/injectqueryclient.md) +- [provideAngularQuery](functions/provideangularquery.md) +- [provideQueryClient](functions/providequeryclient.md) +- [queryOptions](functions/queryoptions.md) diff --git a/docs/framework/angular/reference/interfaces/basemutationnarrowing.md b/docs/framework/angular/reference/interfaces/basemutationnarrowing.md new file mode 100644 index 0000000000..96ddd7fa63 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/basemutationnarrowing.md @@ -0,0 +1,96 @@ +--- +id: BaseMutationNarrowing +title: BaseMutationNarrowing +--- + +# Interface: BaseMutationNarrowing\ + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `unknown` + +• **TContext** = `unknown` + +## Properties + +### isError() + +```ts +isError: (this) => this is CreateMutationResult, Object> & Object>; +``` + +#### Parameters + +• **this**: [`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`, `CreateStatusBasedMutationResult`\<`"error"` \| `"success"` \| `"pending"` \| `"idle"`, `TData`, `TError`, `TVariables`, `TContext`\>\> + +#### Returns + +`this is CreateMutationResult, Object> & Object>` + +#### Defined in + +[types.ts:248](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L248) + +--- + +### isIdle() + +```ts +isIdle: (this) => this is CreateMutationResult, Object> & Object>; +``` + +#### Parameters + +• **this**: [`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`, `CreateStatusBasedMutationResult`\<`"error"` \| `"success"` \| `"pending"` \| `"idle"`, `TData`, `TError`, `TVariables`, `TContext`\>\> + +#### Returns + +`this is CreateMutationResult, Object> & Object>` + +#### Defined in + +[types.ts:278](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L278) + +--- + +### isPending() + +```ts +isPending: (this) => this is CreateMutationResult, Object> & Object>; +``` + +#### Parameters + +• **this**: [`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`, `CreateStatusBasedMutationResult`\<`"error"` \| `"success"` \| `"pending"` \| `"idle"`, `TData`, `TError`, `TVariables`, `TContext`\>\> + +#### Returns + +`this is CreateMutationResult, Object> & Object>` + +#### Defined in + +[types.ts:263](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L263) + +--- + +### isSuccess() + +```ts +isSuccess: (this) => this is CreateMutationResult, Object> & Object>; +``` + +#### Parameters + +• **this**: [`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`, `CreateStatusBasedMutationResult`\<`"error"` \| `"success"` \| `"pending"` \| `"idle"`, `TData`, `TError`, `TVariables`, `TContext`\>\> + +#### Returns + +`this is CreateMutationResult, Object> & Object>` + +#### Defined in + +[types.ts:233](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L233) diff --git a/docs/framework/angular/reference/interfaces/basequerynarrowing.md b/docs/framework/angular/reference/interfaces/basequerynarrowing.md new file mode 100644 index 0000000000..2030db4067 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/basequerynarrowing.md @@ -0,0 +1,72 @@ +--- +id: BaseQueryNarrowing +title: BaseQueryNarrowing +--- + +# Interface: BaseQueryNarrowing\ + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Properties + +### isError() + +```ts +isError: (this) => this is CreateBaseQueryResult>; +``` + +#### Parameters + +• **this**: [`CreateBaseQueryResult`](../type-aliases/createbasequeryresult.md)\<`TData`, `TError`, `QueryObserverResult`\<`TData`, `TError`\>\> + +#### Returns + +`this is CreateBaseQueryResult>` + +#### Defined in + +[types.ts:75](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L75) + +--- + +### isPending() + +```ts +isPending: (this) => this is CreateBaseQueryResult>; +``` + +#### Parameters + +• **this**: [`CreateBaseQueryResult`](../type-aliases/createbasequeryresult.md)\<`TData`, `TError`, `QueryObserverResult`\<`TData`, `TError`\>\> + +#### Returns + +`this is CreateBaseQueryResult>` + +#### Defined in + +[types.ts:82](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L82) + +--- + +### isSuccess() + +```ts +isSuccess: (this) => this is CreateBaseQueryResult>; +``` + +#### Parameters + +• **this**: [`CreateBaseQueryResult`](../type-aliases/createbasequeryresult.md)\<`TData`, `TError`, `QueryObserverResult`\<`TData`, `TError`\>\> + +#### Returns + +`this is CreateBaseQueryResult>` + +#### Defined in + +[types.ts:68](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L68) diff --git a/docs/framework/angular/reference/interfaces/createbasequeryoptions.md b/docs/framework/angular/reference/interfaces/createbasequeryoptions.md new file mode 100644 index 0000000000..c371959980 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/createbasequeryoptions.md @@ -0,0 +1,22 @@ +--- +id: CreateBaseQueryOptions +title: CreateBaseQueryOptions +--- + +# Interface: CreateBaseQueryOptions\ + +## Extends + +- `QueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`\> + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` diff --git a/docs/framework/angular/reference/interfaces/createinfinitequeryoptions.md b/docs/framework/angular/reference/interfaces/createinfinitequeryoptions.md new file mode 100644 index 0000000000..dade8e1e30 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/createinfinitequeryoptions.md @@ -0,0 +1,24 @@ +--- +id: CreateInfiniteQueryOptions +title: CreateInfiniteQueryOptions +--- + +# Interface: CreateInfiniteQueryOptions\ + +## Extends + +- `OmitKeyof`\<`InfiniteQueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`, `TPageParam`\>, `"suspense"`\> + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` diff --git a/docs/framework/angular/reference/interfaces/createmutationoptions.md b/docs/framework/angular/reference/interfaces/createmutationoptions.md new file mode 100644 index 0000000000..ffca256828 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/createmutationoptions.md @@ -0,0 +1,20 @@ +--- +id: CreateMutationOptions +title: CreateMutationOptions +--- + +# Interface: CreateMutationOptions\ + +## Extends + +- `OmitKeyof`\<`MutationObserverOptions`\<`TData`, `TError`, `TVariables`, `TContext`\>, `"_defaulted"`\> + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` diff --git a/docs/framework/angular/reference/interfaces/createqueryoptions.md b/docs/framework/angular/reference/interfaces/createqueryoptions.md new file mode 100644 index 0000000000..739f7179f7 --- /dev/null +++ b/docs/framework/angular/reference/interfaces/createqueryoptions.md @@ -0,0 +1,20 @@ +--- +id: CreateQueryOptions +title: CreateQueryOptions +--- + +# Interface: CreateQueryOptions\ + +## Extends + +- `OmitKeyof`\<[`CreateBaseQueryOptions`](createbasequeryoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`\>, `"suspense"`\> + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` diff --git a/docs/framework/angular/reference/interfaces/injectmutationstateoptions.md b/docs/framework/angular/reference/interfaces/injectmutationstateoptions.md new file mode 100644 index 0000000000..15fe330c5c --- /dev/null +++ b/docs/framework/angular/reference/interfaces/injectmutationstateoptions.md @@ -0,0 +1,18 @@ +--- +id: InjectMutationStateOptions +title: InjectMutationStateOptions +--- + +# Interface: InjectMutationStateOptions + +## Properties + +### injector? + +```ts +optional injector: Injector; +``` + +#### Defined in + +[inject-mutation-state.ts:43](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-mutation-state.ts#L43) diff --git a/docs/framework/angular/reference/type-aliases/createbasemutationresult.md b/docs/framework/angular/reference/type-aliases/createbasemutationresult.md new file mode 100644 index 0000000000..3cad41d423 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createbasemutationresult.md @@ -0,0 +1,32 @@ +--- +id: CreateBaseMutationResult +title: CreateBaseMutationResult +--- + +# Type Alias: CreateBaseMutationResult\ + +```ts +type CreateBaseMutationResult: Override, object> & object; +``` + +## Type declaration + +### mutateAsync + +```ts +mutateAsync: CreateMutateAsyncFunction +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `unknown` + +• **TContext** = `unknown` + +## Defined in + +[types.ts:198](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L198) diff --git a/docs/framework/angular/reference/type-aliases/createbasequeryresult.md b/docs/framework/angular/reference/type-aliases/createbasequeryresult.md new file mode 100644 index 0000000000..3870240677 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createbasequeryresult.md @@ -0,0 +1,22 @@ +--- +id: CreateBaseQueryResult +title: CreateBaseQueryResult +--- + +# Type Alias: CreateBaseQueryResult\ + +```ts +type CreateBaseQueryResult: BaseQueryNarrowing & MapToSignals>; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TState** = `QueryObserverResult`\<`TData`, `TError`\> + +## Defined in + +[types.ts:116](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L116) diff --git a/docs/framework/angular/reference/type-aliases/createinfinitequeryresult.md b/docs/framework/angular/reference/type-aliases/createinfinitequeryresult.md new file mode 100644 index 0000000000..f074b556b7 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createinfinitequeryresult.md @@ -0,0 +1,20 @@ +--- +id: CreateInfiniteQueryResult +title: CreateInfiniteQueryResult +--- + +# Type Alias: CreateInfiniteQueryResult\ + +```ts +type CreateInfiniteQueryResult: MapToSignals>; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[types.ts:143](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L143) diff --git a/docs/framework/angular/reference/type-aliases/createmutateasyncfunction.md b/docs/framework/angular/reference/type-aliases/createmutateasyncfunction.md new file mode 100644 index 0000000000..fd6e7d2012 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createmutateasyncfunction.md @@ -0,0 +1,24 @@ +--- +id: CreateMutateAsyncFunction +title: CreateMutateAsyncFunction +--- + +# Type Alias: CreateMutateAsyncFunction\ + +```ts +type CreateMutateAsyncFunction: MutateFunction; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Defined in + +[types.ts:188](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L188) diff --git a/docs/framework/angular/reference/type-aliases/createmutatefunction.md b/docs/framework/angular/reference/type-aliases/createmutatefunction.md new file mode 100644 index 0000000000..4a8d6580dd --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createmutatefunction.md @@ -0,0 +1,32 @@ +--- +id: CreateMutateFunction +title: CreateMutateFunction +--- + +# Type Alias: CreateMutateFunction()\ + +```ts +type CreateMutateFunction: (...args) => void; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Parameters + +• ...**args**: `Parameters`\<`MutateFunction`\<`TData`, `TError`, `TVariables`, `TContext`\>\> + +## Returns + +`void` + +## Defined in + +[types.ts:176](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L176) diff --git a/docs/framework/angular/reference/type-aliases/createmutationresult.md b/docs/framework/angular/reference/type-aliases/createmutationresult.md new file mode 100644 index 0000000000..7f52e747fb --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createmutationresult.md @@ -0,0 +1,26 @@ +--- +id: CreateMutationResult +title: CreateMutationResult +--- + +# Type Alias: CreateMutationResult\ + +```ts +type CreateMutationResult: BaseMutationNarrowing & MapToSignals>; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `unknown` + +• **TContext** = `unknown` + +• **TState** = `CreateStatusBasedMutationResult`\<[`CreateBaseMutationResult`](createbasemutationresult.md)\[`"status"`\], `TData`, `TError`, `TVariables`, `TContext`\> + +## Defined in + +[types.ts:292](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L292) diff --git a/docs/framework/angular/reference/type-aliases/createqueryresult.md b/docs/framework/angular/reference/type-aliases/createqueryresult.md new file mode 100644 index 0000000000..18b6952820 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/createqueryresult.md @@ -0,0 +1,20 @@ +--- +id: CreateQueryResult +title: CreateQueryResult +--- + +# Type Alias: CreateQueryResult\ + +```ts +type CreateQueryResult: CreateBaseQueryResult; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[types.ts:126](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L126) diff --git a/docs/framework/angular/reference/type-aliases/definedcreateinfinitequeryresult.md b/docs/framework/angular/reference/type-aliases/definedcreateinfinitequeryresult.md new file mode 100644 index 0000000000..5107554d67 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/definedcreateinfinitequeryresult.md @@ -0,0 +1,22 @@ +--- +id: DefinedCreateInfiniteQueryResult +title: DefinedCreateInfiniteQueryResult +--- + +# Type Alias: DefinedCreateInfiniteQueryResult\ + +```ts +type DefinedCreateInfiniteQueryResult: MapToSignals; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TDefinedInfiniteQueryObserver** = `DefinedInfiniteQueryObserverResult`\<`TData`, `TError`\> + +## Defined in + +[types.ts:151](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L151) diff --git a/docs/framework/angular/reference/type-aliases/definedcreatequeryresult.md b/docs/framework/angular/reference/type-aliases/definedcreatequeryresult.md new file mode 100644 index 0000000000..306327f20e --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/definedcreatequeryresult.md @@ -0,0 +1,22 @@ +--- +id: DefinedCreateQueryResult +title: DefinedCreateQueryResult +--- + +# Type Alias: DefinedCreateQueryResult\ + +```ts +type DefinedCreateQueryResult: MapToSignals; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TDefinedQueryObserver** = `DefinedQueryObserverResult`\<`TData`, `TError`\> + +## Defined in + +[types.ts:134](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L134) diff --git a/docs/framework/angular/reference/type-aliases/definedinitialdatainfiniteoptions.md b/docs/framework/angular/reference/type-aliases/definedinitialdatainfiniteoptions.md new file mode 100644 index 0000000000..ad63b14f44 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/definedinitialdatainfiniteoptions.md @@ -0,0 +1,34 @@ +--- +id: DefinedInitialDataInfiniteOptions +title: DefinedInitialDataInfiniteOptions +--- + +# Type Alias: DefinedInitialDataInfiniteOptions\ + +```ts +type DefinedInitialDataInfiniteOptions: CreateInfiniteQueryOptions & object; +``` + +## Type declaration + +### initialData + +```ts +initialData: NonUndefinedGuard> | () => NonUndefinedGuard>; +``` + +## Type Parameters + +• **TQueryFnData** + +• **TError** = `DefaultError` + +• **TData** = `InfiniteData`\<`TQueryFnData`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +## Defined in + +[infinite-query-options.ts:32](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/infinite-query-options.ts#L32) diff --git a/docs/framework/angular/reference/type-aliases/definedinitialdataoptions.md b/docs/framework/angular/reference/type-aliases/definedinitialdataoptions.md new file mode 100644 index 0000000000..f4e8b6da59 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/definedinitialdataoptions.md @@ -0,0 +1,32 @@ +--- +id: DefinedInitialDataOptions +title: DefinedInitialDataOptions +--- + +# Type Alias: DefinedInitialDataOptions\ + +```ts +type DefinedInitialDataOptions: CreateQueryOptions & object; +``` + +## Type declaration + +### initialData + +```ts +initialData: NonUndefinedGuard | () => NonUndefinedGuard; +``` + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[query-options.ts:19](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/query-options.ts#L19) diff --git a/docs/framework/angular/reference/type-aliases/nonundefinedguard.md b/docs/framework/angular/reference/type-aliases/nonundefinedguard.md new file mode 100644 index 0000000000..f2673af9db --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/nonundefinedguard.md @@ -0,0 +1,18 @@ +--- +id: NonUndefinedGuard +title: NonUndefinedGuard +--- + +# Type Alias: NonUndefinedGuard\ + +```ts +type NonUndefinedGuard: T extends undefined ? never : T; +``` + +## Type Parameters + +• **T** + +## Defined in + +[types.ts:316](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/types.ts#L316) diff --git a/docs/framework/angular/reference/type-aliases/queriesoptions.md b/docs/framework/angular/reference/type-aliases/queriesoptions.md new file mode 100644 index 0000000000..e21003d6f9 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/queriesoptions.md @@ -0,0 +1,24 @@ +--- +id: QueriesOptions +title: QueriesOptions +--- + +# Type Alias: QueriesOptions\ + +```ts +type QueriesOptions: TDepth["length"] extends MAXIMUM_DEPTH ? QueryObserverOptionsForCreateQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResult, GetOptions] : T extends [infer Head, ...(infer Tail)] ? QueriesOptions<[...Tail], [...TResult, GetOptions], [...TDepth, 1]> : ReadonlyArray extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[]; +``` + +QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TResult** _extends_ `any`[] = [] + +• **TDepth** _extends_ `ReadonlyArray`\<`number`\> = [] + +## Defined in + +[inject-queries.ts:108](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-queries.ts#L108) diff --git a/docs/framework/angular/reference/type-aliases/queriesresults.md b/docs/framework/angular/reference/type-aliases/queriesresults.md new file mode 100644 index 0000000000..7ff2e3ebd1 --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/queriesresults.md @@ -0,0 +1,24 @@ +--- +id: QueriesResults +title: QueriesResults +--- + +# Type Alias: QueriesResults\ + +```ts +type QueriesResults: TDepth["length"] extends MAXIMUM_DEPTH ? QueryObserverResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResult, GetResults] : T extends [infer Head, ...(infer Tail)] ? QueriesResults<[...Tail], [...TResult, GetResults], [...TDepth, 1]> : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverResult[] : QueryObserverResult[]; +``` + +QueriesResults reducer recursively maps type param to results + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TResult** _extends_ `any`[] = [] + +• **TDepth** _extends_ `ReadonlyArray`\<`number`\> = [] + +## Defined in + +[inject-queries.ts:151](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/inject-queries.ts#L151) diff --git a/docs/framework/angular/reference/type-aliases/undefinedinitialdatainfiniteoptions.md b/docs/framework/angular/reference/type-aliases/undefinedinitialdatainfiniteoptions.md new file mode 100644 index 0000000000..b1bb260cec --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/undefinedinitialdatainfiniteoptions.md @@ -0,0 +1,34 @@ +--- +id: UndefinedInitialDataInfiniteOptions +title: UndefinedInitialDataInfiniteOptions +--- + +# Type Alias: UndefinedInitialDataInfiniteOptions\ + +```ts +type UndefinedInitialDataInfiniteOptions: CreateInfiniteQueryOptions & object; +``` + +## Type declaration + +### initialData? + +```ts +optional initialData: undefined; +``` + +## Type Parameters + +• **TQueryFnData** + +• **TError** = `DefaultError` + +• **TData** = `InfiniteData`\<`TQueryFnData`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +## Defined in + +[infinite-query-options.ts:12](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/infinite-query-options.ts#L12) diff --git a/docs/framework/angular/reference/type-aliases/undefinedinitialdataoptions.md b/docs/framework/angular/reference/type-aliases/undefinedinitialdataoptions.md new file mode 100644 index 0000000000..bf64cf110e --- /dev/null +++ b/docs/framework/angular/reference/type-aliases/undefinedinitialdataoptions.md @@ -0,0 +1,32 @@ +--- +id: UndefinedInitialDataOptions +title: UndefinedInitialDataOptions +--- + +# Type Alias: UndefinedInitialDataOptions\ + +```ts +type UndefinedInitialDataOptions: CreateQueryOptions & object; +``` + +## Type declaration + +### initialData? + +```ts +optional initialData: undefined; +``` + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[query-options.ts:7](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/angular-query-experimental/src/query-options.ts#L7) diff --git a/docs/framework/angular/zoneless.md b/docs/framework/angular/zoneless.md new file mode 100644 index 0000000000..fce6156c02 --- /dev/null +++ b/docs/framework/angular/zoneless.md @@ -0,0 +1,11 @@ +--- +id: zoneless +title: Zoneless Angular +--- + +Because the Angular adapter for TanStack Query is built on signals, it fully supports Zoneless! + +Among Zoneless benefits are improved performance and debugging experience. For details see the [Angular documentation](https://angular.dev/guide/experimental/zoneless). + +> Keep in mind that the API for Angular Zoneless is currently experimental and can change in Angular patch versions. +> Besides Zoneless, ZoneJS change detection is also fully supported. diff --git a/docs/framework/react/community/community-projects.md b/docs/framework/react/community/community-projects.md index e57313e56a..4e46663e0b 100644 --- a/docs/framework/react/community/community-projects.md +++ b/docs/framework/react/community/community-projects.md @@ -85,12 +85,24 @@ A library for creating typesafe standardized query keys, useful for cache manage Link: https://github.com/lukemorales/query-key-factory +## Rapini + +🥬 OpenAPI to React Query (or SWR) & Axios + +Link: https://github.com/rametta/rapini + ## React Query Kit 🕊️ A toolkit for ReactQuery that makes ReactQuery hooks reusable and typesafe Link: https://github.com/liaoliao666/react-query-kit +## React Query Rewind + +Time travel and visualize state during development + +Link: https://reactqueryrewind.com/ + ## React Query Swagger Generate React Query hooks based on Swagger API definitions diff --git a/docs/framework/react/comparison.md b/docs/framework/react/comparison.md index 78e8d2512c..ffc7eb01a8 100644 --- a/docs/framework/react/comparison.md +++ b/docs/framework/react/comparison.md @@ -36,7 +36,7 @@ Feature/Capability Key: | Infinite Queries | ✅ | ✅ | ✅ | 🛑 | 🛑 | | Bi-directional Infinite Queries | ✅ | 🔶 | 🔶 | 🛑 | 🛑 | | Infinite Query Refetching | ✅ | ✅ | 🛑 | 🛑 | 🛑 | -| Lagged Query Data1 | ✅ | ✅ | 🛑 | ✅ | ✅ | +| Lagged Query Data1 | ✅ | ✅ | ✅ | ✅ | ✅ | | Selectors | ✅ | 🛑 | ✅ | ✅ | N/A | | Initial Data | ✅ | ✅ | ✅ | ✅ | ✅ | | Scroll Recovery | ✅ | ✅ | ✅ | ✅ | ✅ | @@ -48,15 +48,15 @@ Feature/Capability Key: | Offline Mutation Support | ✅ | 🛑 | 🟡 | 🛑 | 🛑 | | Prefetching APIs | ✅ | ✅ | ✅ | ✅ | ✅ | | Query Cancellation | ✅ | 🛑 | 🛑 | 🛑 | ✅ | -| Partial Query Matching3 | ✅ | 🔶 | 🛑 | ✅ | N/A | +| Partial Query Matching3 | ✅ | 🔶 | ✅ | ✅ | N/A | | Stale While Revalidate | ✅ | ✅ | ✅ | ✅ | 🛑 | | Stale Time Configuration | ✅ | 🛑7 | 🛑 | ✅ | 🛑 | -| Pre-usage Query/Mutation Configuration4 | ✅ | 🛑 | 🛑 | ✅ | ✅ | +| Pre-usage Query/Mutation Configuration4 | ✅ | 🛑 | ✅ | ✅ | ✅ | | Window Focus Refetching | ✅ | ✅ | 🛑 | ✅ | 🛑 | | Network Status Refetching | ✅ | ✅ | ✅ | ✅ | 🛑 | | General Cache Dehydration/Rehydration | ✅ | 🛑 | ✅ | ✅ | ✅ | | Offline Caching | ✅ | 🛑 | ✅ | 🔶 | 🛑 | -| React Suspense | ✅ | ✅ | 🛑 | 🛑 | ✅ | +| React Suspense | ✅ | ✅ | ✅ | 🛑 | ✅ | | Abstracted/Agnostic Core | ✅ | 🛑 | ✅ | ✅ | 🛑 | | Automatic Refetch after Mutation5 | 🔶 | 🔶 | ✅ | ✅ | ✅ | | Normalized Caching6 | 🛑 | 🛑 | ✅ | 🛑 | 🛑 | diff --git a/docs/framework/react/devtools.md b/docs/framework/react/devtools.md index 7962c97ea7..f3b3b539d0 100644 --- a/docs/framework/react/devtools.md +++ b/docs/framework/react/devtools.md @@ -77,7 +77,7 @@ function App() { - Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. - `shadowDOMTarget?: ShadowRoot` - Default behavior will apply the devtool's styles to the head tag within the DOM. - - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instad of within the head tag in the light DOM. + - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM. ## Devtools in production diff --git a/docs/framework/react/guides/advanced-ssr.md b/docs/framework/react/guides/advanced-ssr.md index abef70e177..bbbac63208 100644 --- a/docs/framework/react/guides/advanced-ssr.md +++ b/docs/framework/react/guides/advanced-ssr.md @@ -29,10 +29,12 @@ The first step of any React Query setup is always to create a `queryClient` and // In Next.js, this file would be called: app/providers.jsx 'use client' -// We can not useState or useRef in a server component, which is why we are -// extracting this part out into it's own file with 'use client' on top -import { useState } from 'react' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +// Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top +import { + isServer, + QueryClient, + QueryClientProvider, +} from '@tanstack/react-query' function makeQueryClient() { return new QueryClient({ @@ -49,12 +51,12 @@ function makeQueryClient() { let browserQueryClient: QueryClient | undefined = undefined function getQueryClient() { - if (typeof window === 'undefined') { + if (isServer) { // Server: always make a new query client return makeQueryClient() } else { // Browser: make a new query client if we don't already have one - // This is very important so we don't re-make a new client if React + // This is very important, so we don't re-make a new client if React // suspends during the initial render. This may not be needed if we // have a suspense boundary BELOW the creation of the query client if (!browserQueryClient) browserQueryClient = makeQueryClient() @@ -190,7 +192,10 @@ Next, we'll look at what the Client Component part looks like: export default function Posts() { // This useQuery could just as well happen in some deeper // child to , data will be available immediately either way - const { data } = useQuery({ queryKey: ['posts'], queryFn: getPosts }) + const { data } = useQuery({ + queryKey: ['posts'], + queryFn: () => getPosts(), + }) // This query was not prefetched on the server and will not start // fetching until on the client, both patterns are fine to mix. @@ -209,6 +214,8 @@ In the SSR guide, we noted that you could get rid of the boilerplate of having ` > NOTE: If you encounter a type error while using async Server Components with TypeScript versions lower than `5.1.3` and `@types/react` versions lower than `18.2.8`, it is recommended to update to the latest versions of both. Alternatively, you can use the temporary workaround of adding `{/* @ts-expect-error Server Component */}` when calling this component inside another. For more information, see [Async Server Component TypeScript Error](https://nextjs.org/docs/app/building-your-application/configuring/typescript#async-server-component-typescript-error) in the Next.js 13 docs. +> NOTE: If you encounter an error `Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.` make sure that you're **not** passing to queryFn a function reference, instead call the function because queryFn args has a bunch of properties and not all of it would be serializable. see [Server Action only works when queryFn isn't a reference](https://github.com/TanStack/query/issues/6264). + ### Nesting Server Components A nice thing about Server Components is that they can be nested and exist on many levels in the React tree, making it possible to prefetch data closer to where it's actually used instead of only at the top of the application (just like Remix loaders). This can be as simple as a Server Component rendering another Server Component (we'll leave the Client Components out in this example for brevity): @@ -356,9 +363,158 @@ The Next.js app router automatically streams any part of the application that is With the prefetching patterns described above, React Query is perfectly compatible with this form of streaming. As the data for each Suspense boundary resolves, Next.js can render and stream the finished content to the browser. This works even if you are using `useQuery` as outlined above because the suspending actually happens when you `await` the prefetch. -Note that right now, you have to await all prefetches for this to work. This means all prefetches are considered critical content and will block that Suspense boundary. +As of React Query v5.40.0, you don't have to `await` all prefetches for this to work, as `pending` Queries can also be dehydrated and sent to the client. This lets you kick off prefetches as early as possible without letting them block an entire Suspense boundary, and streams the _data_ to the client as the query finishes. This can be useful for example if you want to prefetch some content that is only visible after some user interaction, or say if you want to `await` and render the first page of an infinite query, but start prefetching page 2 without blocking rendering. + +To make this work, we have to instruct the `queryClient` to also `dehydrate` pending Queries. We can do this globally, or by passing that option directly to `hydrate`. + +We will also need to move the `getQueryClient()` function out of our `app/providers.jsx` file as we want to use it in our server component and our client provider. + +```tsx +// app/get-query-client.ts +import { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query' + +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, + }, + dehydrate: { + // include pending queries in dehydration + shouldDehydrateQuery: (query) => + defaultShouldDehydrateQuery(query) || + query.state.status === 'pending', + }, + }, + }) +} + +let browserQueryClient: QueryClient | undefined = undefined + +export function getQueryClient() { + if (isServer) { + // Server: always make a new query client + return makeQueryClient() + } else { + // Browser: make a new query client if we don't already have one + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient() + return browserQueryClient + } +} +``` + +> Note: This works in NextJs and Server Components because React can serialize Promises over the wire when you pass them down to Client Components. + +Then, all we need to do is provide a `HydrationBoundary`, but we don't need to `await` prefetches anymore: + +```tsx +// app/posts/page.jsx +import { dehydrate, HydrationBoundary } from '@tanstack/react-query' +import { getQueryClient } from './get-query-client' +import Posts from './posts' + +// the function doesn't need to be `async` because we don't `await` anything +export default function PostsPage() { + const queryClient = getQueryClient() + + // look ma, no await + queryClient.prefetchQuery({ + queryKey: ['posts'], + queryFn: getPosts, + }) + + return ( + + + + ) +} +``` + +On the client, the Promise will be put into the QueryCache for us. That means we can now call `useSuspenseQuery` inside the `Posts` component to "use" that Promise (which was created on the Server): + +```tsx +// app/posts/posts.tsx +'use client' + +export default function Posts() { + const { data } = useSuspenseQuery({ queryKey: ['posts'], queryFn: getPosts }) + + // ... +} +``` + +> Note that you could also `useQuery` instead of `useSuspenseQuery`, and the Promise would still be picked up correctly. However, NextJs won't suspend in that case and the component will render in the `pending` status, which also opts out of server rendering the content. + +If you're using non-JSON data types and serialize the query results on the server, you can specify the `dehydrate.serializeData` and `hydrate.deserializeData` options to serialize and deserialize the data on each side of the boundary to ensure the data in the cache is the same format both on the server and the client: + +```tsx +// app/get-query-client.ts +import { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query' +import { deserialize, serialize } from './transformer' + +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + // ... + hydrate: { + deserializeData: deserialize, + }, + dehydrate: { + serializeData: serialize, + }, + }, + }) +} + +// ... +``` + +```tsx +// app/posts/page.tsx +import { + dehydrate, + HydrationBoundary, + QueryClient, +} from '@tanstack/react-query' +import { getQueryClient } from './get-query-client' +import { serialize } from './transformer' +import Posts from './posts' + +export default function PostsPage() { + const queryClient = getQueryClient() -As an aside, in the future it might be possible to skip the await for "optional" prefetches that are not critical for this Suspense boundary. This would let you kick off prefetches as early as possible without letting them block an entire Suspense boundary, and streaming the _data_ to the client as the query finishes. This could be useful for example if you want to prefetch some content that is only visible after some user interaction, or say if you want to await and render the first page of an infinite query, but start prefetching page 2 without blocking rendering. + // look ma, no await + queryClient.prefetchQuery({ + queryKey: ['posts'], + queryFn: () => getPosts().then(serialize), // <-- serialize the data on the server + }) + + return ( + + + + ) +} +``` + +```tsx +// app/posts/posts.tsx +'use client' + +export default function Posts() { + const { data } = useSuspenseQuery({ queryKey: ['posts'], queryFn: getPosts }) + + // ... +} +``` + +Now, your `getPosts` function can return e.g. `Temporal` datetime objects and the data will be serialized and deserialized on the client, assuming your transformer can serialize and deserialize those data types. + +For more information, check out the [Next.js App with Prefetching Example](../../examples/nextjs-app-prefetching). ## Experimental streaming without prefetching in Next.js @@ -372,7 +528,11 @@ To achieve this, wrap your app in the `ReactQueryStreamedHydration` component: // app/providers.tsx 'use client' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + isServer, + QueryClient, + QueryClientProvider, +} from '@tanstack/react-query' import * as React from 'react' import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental' @@ -391,13 +551,13 @@ function makeQueryClient() { let browserQueryClient: QueryClient | undefined = undefined function getQueryClient() { - if (typeof window === 'undefined') { + if (isServer) { // Server: always make a new query client return makeQueryClient() } else { // Browser: make a new query client if we don't already have one - // This is very important so we don't re-make a new client if React - // supsends during the initial render. This may not be needed if we + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we // have a suspense boundary BELOW the creation of the query client if (!browserQueryClient) browserQueryClient = makeQueryClient() return browserQueryClient diff --git a/docs/framework/react/guides/disabling-queries.md b/docs/framework/react/guides/disabling-queries.md index 6893039809..da173f688b 100644 --- a/docs/framework/react/guides/disabling-queries.md +++ b/docs/framework/react/guides/disabling-queries.md @@ -3,7 +3,7 @@ id: disabling-queries title: Disabling/Pausing Queries --- -If you ever want to disable a query from automatically running, you can use the `enabled = false` option. +If you ever want to disable a query from automatically running, you can use the `enabled = false` option. The enabled option also accepts a callback that returns a boolean. When `enabled` is `false`: diff --git a/docs/framework/react/guides/filters.md b/docs/framework/react/guides/filters.md index daca12f69f..a4e20cde67 100644 --- a/docs/framework/react/guides/filters.md +++ b/docs/framework/react/guides/filters.md @@ -70,3 +70,21 @@ A mutation filter object supports the following properties: - Allows for filtering mutations according to their status. - `predicate?: (mutation: Mutation) => boolean` - This predicate function will be used as a final filter on all matching mutations. If no other filters are specified, this function will be evaluated against every mutation in the cache. + +## Utils + +### `matchQuery` + +```tsx +const isMatching = matchQuery(filters, query) +``` + +Returns a boolean that indicates whether a query matches the provided set of query filters. + +### `matchMutation` + +```tsx +const isMatching = matchMutation(filters, mutation) +``` + +Returns a boolean that indicates whether a mutation matches the provided set of mutation filters. diff --git a/docs/framework/react/guides/migrating-to-v5.md b/docs/framework/react/guides/migrating-to-v5.md index aa6ea1a741..ac9f7a5012 100644 --- a/docs/framework/react/guides/migrating-to-v5.md +++ b/docs/framework/react/guides/migrating-to-v5.md @@ -179,7 +179,7 @@ TanStack Query has always had private fields and methods on classes, but they we Almost everyone gets `cacheTime` wrong. It sounds like "the amount of time that data is cached for", but that is not correct. -`cacheTime` does nothing as long as a query is still in used. It only kicks in as soon as the query becomes unused. After the time has passed, data will be "garbage collected" to avoid the cache from growing. +`cacheTime` does nothing as long as a query is still in use. It only kicks in as soon as the query becomes unused. After the time has passed, data will be "garbage collected" to avoid the cache from growing. `gc` is referring to "garbage collect" time. It's a bit more technical, but also a quite [well known abbreviation]() in computer science. @@ -365,7 +365,7 @@ For mutations as well the `status` has been changed from `loading` to `pending` Lastly, a new derived `isLoading` flag has been added to the queries that is implemented as `isPending && isFetching`. This means that `isLoading` and `isInitialLoading` have the same thing, but `isInitialLoading` is deprecated now and will be removed in the next major version. -To understand the reasoning behing this change checkout the [v5 roadmap discussion](https://github.com/TanStack/query/discussions/4252). +To understand the reasoning behind this change checkout the [v5 roadmap discussion](https://github.com/TanStack/query/discussions/4252). ### `hashQueryKey` has been renamed to `hashKey` @@ -381,7 +381,7 @@ React Query v5 requires React 18.0 or later. This is because we are using the ne You could previously use the `contextSharing` property to share the first (and at least one) instance of the query client context across the window. This ensured that if TanStack Query was used across different bundles or microfrontends then they will all use the same instance of the context, regardless of module scoping. -However, isolation is often preferred for microfrontends. In v4 the option to pass a custom context to the `QueryClientProvider` was added, which allows exactly this. If you wish to use the same query client across multiple packages of an application, you can create a `QueryClient` in your application and then let the bundles share this through the `context` property of the `QueryClientProvider`. +With the removal of the custom context prop in v5, refer to the section on [Removed custom context prop in favor of custom queryClient instance](#removed-custom-context-prop-in-favor-of-custom-queryclient-instance). If you wish to share the same query client across multiple packages of an application, you can directly pass a shared custom `queryClient` instance. ### No longer using `unstable_batchedUpdates` as the batching function in React and React Native diff --git a/docs/framework/react/guides/mutations.md b/docs/framework/react/guides/mutations.md index 200978a842..7208aee74d 100644 --- a/docs/framework/react/guides/mutations.md +++ b/docs/framework/react/guides/mutations.md @@ -388,8 +388,6 @@ export default function App() { We also have an extensive [offline example](../../examples/offline) that covers both queries and mutations. -[//]: # 'Materials' - ## Mutation Scopes Per default, all mutations run in parallel - even if you invoke `.mutate()` of the same mutation multiple times. Mutations can be given a `scope` with an `id` to avoid that. All mutations with the same `scope.id` will run in serial, which means when they are triggered, they will start in `isPaused: true` state if there is already a mutation for that scope in progress. They will be put into a queue and will automatically resume once their time in the queue has come. @@ -406,6 +404,7 @@ const mutation = useMutation({ ``` [//]: # 'ExampleScopes' +[//]: # 'Materials' ## Further reading diff --git a/docs/framework/react/guides/optimistic-updates.md b/docs/framework/react/guides/optimistic-updates.md index f733d305b1..b7607c41e7 100644 --- a/docs/framework/react/guides/optimistic-updates.md +++ b/docs/framework/react/guides/optimistic-updates.md @@ -12,7 +12,7 @@ This is the simpler variant, as it doesn't interact with the cache directly. [//]: # 'ExampleUI1' ```tsx -const { isPending, submittedAt, variables, mutate, isError } = useMutation({ +const addTodoMutation = useMutation({ mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }), // make sure to _return_ the Promise from the query invalidation // so that the mutation stays in `pending` state until the refetch is finished @@ -20,11 +20,13 @@ const { isPending, submittedAt, variables, mutate, isError } = useMutation({ return await queryClient.invalidateQueries({ queryKey: ['todos'] }) }, }) + +const { isPending, submittedAt, variables, mutate, isError } = addTodoMutation ``` [//]: # 'ExampleUI1' -you will then have access to `addTodoMutation.variables`, which contain the added todo. In your UI list, where the query is rendered, you can append another item to the list while the mutation is `pending`: +you will then have access to `addTodoMutation.variables`, which contain the added todo. In your UI list, where the query is rendered, you can append another item to the list while the mutation `isPending`: [//]: # 'ExampleUI2' diff --git a/docs/framework/react/guides/paginated-queries.md b/docs/framework/react/guides/paginated-queries.md index 7ddb8b348a..e46131ab1e 100644 --- a/docs/framework/react/guides/paginated-queries.md +++ b/docs/framework/react/guides/paginated-queries.md @@ -68,7 +68,7 @@ function Todos() { disabled={page === 0} > Previous Page - {' '} + - {isFetching ? Loading... : null}{' '} + {isFetching ? Loading... : null}
) } diff --git a/docs/framework/react/guides/prefetching.md b/docs/framework/react/guides/prefetching.md index b60e8cb344..53b2e4e8a8 100644 --- a/docs/framework/react/guides/prefetching.md +++ b/docs/framework/react/guides/prefetching.md @@ -196,41 +196,41 @@ This starts fetching `'article-comments'` immediately and flattens the waterfall [//]: # 'Suspense' -If you want to prefetch together with Suspense, you will have to do things a bit differently. You can't use `useSuspenseQueries` to prefetch, since the prefetch would block the component from rendering. You also can not use `useQuery` for the prefetch, because that wouldn't start the prefetch until after suspenseful query had resolved. What you can do is add a small `usePrefetchQuery` function (we might add this to the library itself at a later point): - -```tsx -const usePrefetchQuery = (...args) => { - const queryClient = useQueryClient() - - // This happens in render, but is safe to do because ensureQueryData - // only fetches if there is no data in the cache for this query. This - // means we know no observers are watching the data so the side effect - // is not observable, which is safe. - queryClient.ensureQueryData(...args) -} -``` - -This approach works with both `useQuery` and `useSuspenseQuery`, so feel free to use it as an alternative to the `useQuery({ ..., notifyOnChangeProps: [] })` approach as well. The only tradeoff is that the above function will never fetch and _update_ existing data in the cache if it's stale, but this will usually happen in the later query anyway. +If you want to prefetch together with Suspense, you will have to do things a bit differently. You can't use `useSuspenseQueries` to prefetch, since the prefetch would block the component from rendering. You also can not use `useQuery` for the prefetch, because that wouldn't start the prefetch until after suspenseful query had resolved. For this scenario, you can use the [`usePrefetchQuery`](../../reference/usePrefetchQuery) or the [`usePrefetchInfiniteQuery`](../../reference/usePrefetchInfiniteQuery) hooks available in the library. You can now use `useSuspenseQuery` in the component that actually needs the data. You _might_ want to wrap this later component in its own `` boundary so the "secondary" query we are prefetching does not block rendering of the "primary" data. ```tsx -// Prefetch -usePrefetchQuery({ - queryKey: ['article-comments', id], - queryFn: getArticleCommentsById, -}) +function App() { + usePrefetchQuery({ + queryKey: ['articles'], + queryFn: (...args) => { + return getArticles(...args) + }, + }) -const { data: articleResult } = useSuspenseQuery({ - queryKey: ['article', id], - queryFn: getArticleById, -}) + return ( + + + + ) +} -// In nested component: -const { data: commentsResult } = useSuspenseQuery({ - queryKey: ['article-comments', id], - queryFn: getArticleCommentsById, -}) +function Articles() { + const { data: articles } = useSuspenseQuery({ + queryKey: ['articles'], + queryFn: (...args) => { + return getArticles(...args) + }, + }) + + return articles.map((article) => ( +
+ + +
+ )) +} ``` Another way is to prefetch inside of the query function. This makes sense if you know that every time an article is fetched it's very likely comments will also be needed. For this, we'll use `queryClient.prefetchQuery`: @@ -265,6 +265,7 @@ useEffect(() => { To recap, if you want to prefetch a query during the component lifecycle, there are a few different ways to do it, pick the one that suits your situation best: +- Prefetch before a suspense boundary using `usePrefetchQuery` or `usePrefetchInfiniteQuery` hooks - Use `useQuery` or `useSuspenseQueries` and ignore the result - Prefetch inside the query function - Prefetch in an effect @@ -377,7 +378,7 @@ Because data fetching in the component tree itself can easily lead to request wa In this approach, you explicitly declare for each _route_ what data is going to be needed for that component tree, ahead of time. Because Server Rendering has traditionally needed all data to be loaded before rendering starts, this has been the dominating approach for SSR'd apps for a long time. This is still a common approach and you can read more about it in the [Server Rendering & Hydration guide](../ssr). -For now, let's focus on the client side case and look at an example of how you can make this work with [Tanstack Router](https://tanstack.com/router). These examples leave out a lot of setup and boilerplate to stay concise, you can check out a [full React Query example](https://tanstack.com/router/v1/docs/examples/react/with-react-query?file=src%2Fmain.tsx) over in the [Tanstack Router docs](https://tanstack.com/router/v1/docs). +For now, let's focus on the client side case and look at an example of how you can make this work with [Tanstack Router](https://tanstack.com/router). These examples leave out a lot of setup and boilerplate to stay concise, you can check out a [full React Query example](https://tanstack.com/router/v1/docs/framework/react/examples/basic-react-query-file-based) over in the [Tanstack Router docs](https://tanstack.com/router/v1/docs). When integrating at the router level, you can choose to either _block_ rendering of that route until all data is present, or you can start a prefetch but not await the result. That way, you can start rendering the route as soon as possible. You can also mix these two approaches and await some critical data, but start rendering before all the secondary data has finished loading. In this example, we'll configure an `/article` route to not render until the article data has finished loading, as well as start prefetching comments as soon as possible, but not block rendering the route if comments haven't finished loading yet. diff --git a/docs/framework/react/guides/query-functions.md b/docs/framework/react/guides/query-functions.md index 7b3779c3d0..92faed581e 100644 --- a/docs/framework/react/guides/query-functions.md +++ b/docs/framework/react/guides/query-functions.md @@ -111,4 +111,6 @@ Additionally, [Infinite Queries](../infinite-queries) get the following options - `pageParam: TPageParam` - the page parameter used to fetch the current page - `direction: 'forward' | 'backward'` + - **deprecated** - the direction of the current page fetch + - To get access to the direction of the current page fetch, please add a direction to `pageParam` from `getNextPageParam` and `getPreviousPageParam`. diff --git a/docs/framework/react/guides/query-options.md b/docs/framework/react/guides/query-options.md index e9e702d294..08c80c0311 100644 --- a/docs/framework/react/guides/query-options.md +++ b/docs/framework/react/guides/query-options.md @@ -3,7 +3,7 @@ id: query-options title: Query Options --- -One of the best ways to share `queryKey` and `queryFn` between multiple places, yet keep them co-located to one another, is to use the `queryOptions` helper. At runtime, this helper just returns whatever you pass into it, but it has a lot of advantages when using it [with TypeScript](../../../react/typescript#typing-query-options). You can define all possible options for a query in one place, and you'll also get type inference and type safety for all of them. +One of the best ways to share `queryKey` and `queryFn` between multiple places, yet keep them co-located to one another, is to use the `queryOptions` helper. At runtime, this helper just returns whatever you pass into it, but it has a lot of advantages when using it [with TypeScript](../../typescript#typing-query-options). You can define all possible options for a query in one place, and you'll also get type inference and type safety for all of them. [//]: # 'Example1' diff --git a/docs/framework/react/guides/ssr.md b/docs/framework/react/guides/ssr.md index 7af63a9df8..ed109fcb74 100644 --- a/docs/framework/react/guides/ssr.md +++ b/docs/framework/react/guides/ssr.md @@ -476,7 +476,7 @@ dehydrate(queryClient, { When doing `return { props: { dehydratedState: dehydrate(queryClient) } }` in Next.js, or `return json({ dehydratedState: dehydrate(queryClient) })` in Remix, what happens is that the `dehydratedState` representation of the `queryClient` is serialized by the framework so it can be embedded into the markup and transported to the client. -By default, these frameworks only supports returning things that are safely serializable/parsable, and therefor does not support `undefined`, `Error`, `Date`, `Map`, `Set`, `BigInt`, `Infinity`, `NaN`, `-0`, regular expressions etc. This also means that you can not return any of these things from your queries. If returning these values is something you want, check out [superjson](https://github.com/blitz-js/superjson) or similar packages. +By default, these frameworks only supports returning things that are safely serializable/parsable, and therefore does not support `undefined`, `Error`, `Date`, `Map`, `Set`, `BigInt`, `Infinity`, `NaN`, `-0`, regular expressions etc. This also means that you can not return any of these things from your queries. If returning these values is something you want, check out [superjson](https://github.com/blitz-js/superjson) or similar packages. If you are using a custom SSR setup, you need to take care of this step yourself. Your first instinct might be to use `JSON.stringify(dehydratedState)`, but because this doesn't escape things like `` by default, this can easily lead to **XSS-vulnerabilities** in your application. [superjson](https://github.com/blitz-js/superjson) also **does not** escape values and is unsafe to use by itself in a custom SSR setup (unless you add an extra step for escaping the output). Instead we recommend using a library like [Serialize JavaScript](https://github.com/yahoo/serialize-javascript) or [devalue](https://github.com/Rich-Harris/devalue) which are both safe against XSS injections out of the box. diff --git a/docs/framework/react/guides/suspense.md b/docs/framework/react/guides/suspense.md index 368a331ac1..8049078587 100644 --- a/docs/framework/react/guides/suspense.md +++ b/docs/framework/react/guides/suspense.md @@ -40,9 +40,9 @@ Since you can't change `throwOnError` (because it would allow for `data` to beco ```tsx import { useSuspenseQuery } from '@tanstack/react-query' -const { data, error } = useSuspenseQuery({ queryKey, queryFn }) +const { data, error, isFetching } = useSuspenseQuery({ queryKey, queryFn }) -if (error) { +if (error && !isFetching) { throw error } @@ -118,12 +118,48 @@ To achieve this, wrap your app in the `ReactQueryStreamedHydration` component: // app/providers.tsx 'use client' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + isServer, + QueryClient, + QueryClientProvider, +} from '@tanstack/react-query' import * as React from 'react' import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental' +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 60 * 1000, + }, + }, + }) +} + +let browserQueryClient: QueryClient | undefined = undefined + +function getQueryClient() { + if (isServer) { + // Server: always make a new query client + return makeQueryClient() + } else { + // Browser: make a new query client if we don't already have one + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient() + return browserQueryClient + } +} + export function Providers(props: { children: React.ReactNode }) { - const [queryClient] = React.useState(() => new QueryClient()) + // NOTE: Avoid useState when initializing the query client if you don't + // have a suspense boundary between this and the code that may + // suspend because React will throw away the client on the initial + // render if it suspends and there is no boundary + const queryClient = getQueryClient() return ( diff --git a/docs/framework/react/guides/window-focus-refetching.md b/docs/framework/react/guides/window-focus-refetching.md index b5e9b52b4b..b2a4cbd3e5 100644 --- a/docs/framework/react/guides/window-focus-refetching.md +++ b/docs/framework/react/guides/window-focus-refetching.md @@ -50,10 +50,13 @@ In rare circumstances, you may want to manage your own window focus events that focusManager.setEventListener((handleFocus) => { // Listen to visibilitychange if (typeof window !== 'undefined' && window.addEventListener) { - window.addEventListener('visibilitychange', () => handleFocus(), false) + const visibilitychangeHandler = () => { + handleFocus(document.visibilityState === 'visible') + } + window.addEventListener('visibilitychange', visibilitychangeHandler, false) return () => { // Be sure to unsubscribe if a new handler is set - window.removeEventListener('visibilitychange', () => handleFocus()) + window.removeEventListener('visibilitychange', visibilitychangeHandler) } } }) diff --git a/docs/framework/react/installation.md b/docs/framework/react/installation.md index 46862e7d6d..ab0116f674 100644 --- a/docs/framework/react/installation.md +++ b/docs/framework/react/installation.md @@ -10,13 +10,13 @@ or a good ol' ` + + +``` + +## Extends + +- `SvelteComponent_1`\<`Props`, `Events`\> + +## Type Parameters + +• **Props** _extends_ `Record`\<`string`, `any`\> = `any` + +• **Events** _extends_ `Record`\<`string`, `any`\> = `any` + +• **Slots** _extends_ `Record`\<`string`, `any`\> = `any` + +## Indexable + +\[`prop`: `string`\]: `any` + +## Constructors + +### new HydrationBoundary() + +```ts +new HydrationBoundary(options): HydrationBoundary +``` + +#### Parameters + +• **options**: `ComponentConstructorOptions`\<`Props`\> + +#### Returns + +[`HydrationBoundary`](hydrationboundary.md)\<`Props`, `Events`, `Slots`\> + +#### Overrides + +`SvelteComponent_1.constructor` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:144 + +## Properties + +### $$ + +```ts +$$: any +``` + +### PRIVATE API + +Do not use, may change at any time + +#### Inherited from + +`SvelteComponent_1.$$` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:102 + +--- + +### $$events_def + +```ts +$$events_def: Events +``` + +For type checking capabilities only. +Does not exist at runtime. + +### DO NOT USE! + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:158 + +--- + +### $$prop_def + +```ts +$$prop_def: Props +``` + +For type checking capabilities only. +Does not exist at runtime. + +### DO NOT USE! + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:151 + +--- + +### $$set + +```ts +$$set: any +``` + +### PRIVATE API + +Do not use, may change at any time + +#### Inherited from + +`SvelteComponent_1.$$set` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:109 + +--- + +### $$slot_def + +```ts +$$slot_def: Slots +``` + +For type checking capabilities only. +Does not exist at runtime. + +### DO NOT USE! + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:165 + +## Methods + +### $capture_state() + +```ts +$capture_state(): void +``` + +#### Returns + +`void` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:167 + +--- + +### $destroy() + +```ts +$destroy(): void +``` + +#### Returns + +`void` + +#### Inherited from + +`SvelteComponent_1.$destroy` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:111 + +--- + +### $inject_state() + +```ts +$inject_state(): void +``` + +#### Returns + +`void` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:169 + +--- + +### $on() + +```ts +$on(type, callback): () => void +``` + +#### Type Parameters + +• **K** _extends_ `string` + +#### Parameters + +• **type**: `K` + +• **callback**: `undefined` \| `null` \| (`e`) => `void` + +#### Returns + +`Function` + +##### Returns + +`void` + +#### Inherited from + +`SvelteComponent_1.$on` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:113 + +--- + +### $set() + +```ts +$set(props): void +``` + +#### Parameters + +• **props**: `Partial`\<`Props`\> + +#### Returns + +`void` + +#### Inherited from + +`SvelteComponent_1.$set` + +#### Defined in + +node_modules/.pnpm/svelte@4.2.18/node_modules/svelte/types/index.d.ts:115 diff --git a/docs/framework/svelte/reference/functions/createinfinitequery.md b/docs/framework/svelte/reference/functions/createinfinitequery.md new file mode 100644 index 0000000000..a067f73775 --- /dev/null +++ b/docs/framework/svelte/reference/functions/createinfinitequery.md @@ -0,0 +1,42 @@ +--- +id: createInfiniteQuery +title: createInfiniteQuery +--- + +# Function: createInfiniteQuery() + +```ts +function createInfiniteQuery< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>(options, queryClient?): CreateInfiniteQueryResult +``` + +## Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +## Parameters + +• **options**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`CreateInfiniteQueryOptions`](../type-aliases/createinfinitequeryoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `TPageParam`\>\> + +• **queryClient?**: `QueryClient` + +## Returns + +[`CreateInfiniteQueryResult`](../type-aliases/createinfinitequeryresult.md)\<`TData`, `TError`\> + +## Defined in + +[packages/svelte-query/src/createInfiniteQuery.ts:16](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createInfiniteQuery.ts#L16) diff --git a/docs/framework/svelte/reference/functions/createmutation.md b/docs/framework/svelte/reference/functions/createmutation.md new file mode 100644 index 0000000000..ad11e8c6e9 --- /dev/null +++ b/docs/framework/svelte/reference/functions/createmutation.md @@ -0,0 +1,37 @@ +--- +id: createMutation +title: createMutation +--- + +# Function: createMutation() + +```ts +function createMutation( + options, + queryClient?, +): CreateMutationResult +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `Error` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Parameters + +• **options**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`CreateMutationOptions`](../type-aliases/createmutationoptions.md)\<`TData`, `TError`, `TVariables`, `TContext`\>\> + +• **queryClient?**: `QueryClient` + +## Returns + +[`CreateMutationResult`](../type-aliases/createmutationresult.md)\<`TData`, `TError`, `TVariables`, `TContext`\> + +## Defined in + +[packages/svelte-query/src/createMutation.ts:13](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createMutation.ts#L13) diff --git a/docs/framework/svelte/reference/functions/createqueries.md b/docs/framework/svelte/reference/functions/createqueries.md new file mode 100644 index 0000000000..90a77b2a1c --- /dev/null +++ b/docs/framework/svelte/reference/functions/createqueries.md @@ -0,0 +1,37 @@ +--- +id: createQueries +title: createQueries +--- + +# Function: createQueries() + +```ts +function createQueries( + __namedParameters, + queryClient?, +): Readable +``` + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TCombinedResult** = `T` _extends_ [] ? [] : `T` _extends_ [`Head`] ? [`GetCreateQueryResult`\<`Head`\>] : `T` _extends_ [`Head`, `...Tails[]`] ? [`...Tails[]`] _extends_ [] ? [] : [`...Tails[]`] _extends_ [`Head`] ? [`GetCreateQueryResult`\<`Head`\>, `GetCreateQueryResult`\<`Head`\>] : [`...Tails[]`] _extends_ [`Head`, `...Tails[]`] ? [`...Tails[]`] _extends_ [] ? [] : [`...Tails[]`] _extends_ [`Head`] ? [`GetCreateQueryResult`\<`Head`\>, `GetCreateQueryResult`\<`Head`\>, `GetCreateQueryResult`\<`Head`\>] : [`...Tails[]`] _extends_ [`Head`, `...Tails[]`] ? [`...(...)[]`] _extends_ [] ? [] : ... _extends_ ... ? ... : ... : [`...(...)[]`] _extends_ ...[] ? ...[] : ...[] : [`...Tails[]`] _extends_ `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `any`\>[] ? `QueryObserverResult`\<`unknown` _extends_ `TData` ? `TQueryFnData` : `TData`, `unknown` _extends_ `TError` ? `Error` : `TError`\>[] : `QueryObserverResult`[] : `T` _extends_ `QueryObserverOptionsForCreateQueries`\<`TQueryFnData`, `TError`, `TData`, `any`\>[] ? `QueryObserverResult`\<`unknown` _extends_ `TData` ? `TQueryFnData` : `TData`, `unknown` _extends_ `TError` ? `Error` : `TError`\>[] : `QueryObserverResult`[] + +## Parameters + +• **\_\_namedParameters** + +• **\_\_namedParameters.combine?** + +• **\_\_namedParameters.queries?**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`...(T extends [] ? [] : T extends [Head] ? [GetQueryObserverOptionsForCreateQueries] : T extends [Head, ...Tails[]] ? [...Tails[]] extends [] ? [] : [...Tails[]] extends [Head] ? [GetQueryObserverOptionsForCreateQueries, GetQueryObserverOptionsForCreateQueries] : [...Tails[]] extends [Head, ...Tails[]] ? [...(...)[]] extends [] ? [] : (...) extends (...) ? (...) : (...) : readonly (...)[] extends [...(...)[]] ? [...(...)[]] : (...) extends (...) ? (...) : (...) : readonly unknown[] extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[])[]`]\> + +• **queryClient?**: `QueryClient` + +## Returns + +`Readable`\<`TCombinedResult`\> + +## Defined in + +[packages/svelte-query/src/createQueries.ts:205](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQueries.ts#L205) diff --git a/docs/framework/svelte/reference/functions/createquery.md b/docs/framework/svelte/reference/functions/createquery.md new file mode 100644 index 0000000000..605fbc1f99 --- /dev/null +++ b/docs/framework/svelte/reference/functions/createquery.md @@ -0,0 +1,105 @@ +--- +id: createQuery +title: createQuery +--- + +# Function: createQuery() + +## createQuery(options, queryClient) + +```ts +function createQuery( + options, + queryClient?, +): DefinedCreateQueryResult +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`DefinedInitialDataOptions`](../type-aliases/definedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>\> + +• **queryClient?**: `QueryClient` + +### Returns + +[`DefinedCreateQueryResult`](../type-aliases/definedcreatequeryresult.md)\<`TData`, `TError`\> + +### Defined in + +[packages/svelte-query/src/createQuery.ts:15](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQuery.ts#L15) + +## createQuery(options, queryClient) + +```ts +function createQuery( + options, + queryClient?, +): CreateQueryResult +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`UndefinedInitialDataOptions`](../type-aliases/undefinedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>\> + +• **queryClient?**: `QueryClient` + +### Returns + +[`CreateQueryResult`](../type-aliases/createqueryresult.md)\<`TData`, `TError`\> + +### Defined in + +[packages/svelte-query/src/createQuery.ts:27](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQuery.ts#L27) + +## createQuery(options, queryClient) + +```ts +function createQuery( + options, + queryClient?, +): CreateQueryResult +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`StoreOrVal`](../type-aliases/storeorval.md)\<[`CreateQueryOptions`](../type-aliases/createqueryoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>\> + +• **queryClient?**: `QueryClient` + +### Returns + +[`CreateQueryResult`](../type-aliases/createqueryresult.md)\<`TData`, `TError`\> + +### Defined in + +[packages/svelte-query/src/createQuery.ts:39](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQuery.ts#L39) diff --git a/docs/framework/svelte/reference/functions/getisrestoringcontext.md b/docs/framework/svelte/reference/functions/getisrestoringcontext.md new file mode 100644 index 0000000000..22aa563796 --- /dev/null +++ b/docs/framework/svelte/reference/functions/getisrestoringcontext.md @@ -0,0 +1,20 @@ +--- +id: getIsRestoringContext +title: getIsRestoringContext +--- + +# Function: getIsRestoringContext() + +```ts +function getIsRestoringContext(): Readable +``` + +Retrieves a `isRestoring` from Svelte's context + +## Returns + +`Readable`\<`boolean`\> + +## Defined in + +[packages/svelte-query/src/context.ts:28](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/context.ts#L28) diff --git a/docs/framework/svelte/reference/functions/getqueryclientcontext.md b/docs/framework/svelte/reference/functions/getqueryclientcontext.md new file mode 100644 index 0000000000..f311a473f6 --- /dev/null +++ b/docs/framework/svelte/reference/functions/getqueryclientcontext.md @@ -0,0 +1,20 @@ +--- +id: getQueryClientContext +title: getQueryClientContext +--- + +# Function: getQueryClientContext() + +```ts +function getQueryClientContext(): QueryClient +``` + +Retrieves a Client from Svelte's context + +## Returns + +`QueryClient` + +## Defined in + +[packages/svelte-query/src/context.ts:9](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/context.ts#L9) diff --git a/docs/framework/svelte/reference/functions/infinitequeryoptions.md b/docs/framework/svelte/reference/functions/infinitequeryoptions.md new file mode 100644 index 0000000000..3e9a0c5b4b --- /dev/null +++ b/docs/framework/svelte/reference/functions/infinitequeryoptions.md @@ -0,0 +1,49 @@ +--- +id: infiniteQueryOptions +title: infiniteQueryOptions +--- + +# Function: infiniteQueryOptions() + +```ts +function infiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryKey, + TPageParam, +>( + options, +): CreateInfiniteQueryOptions< + TQueryFnData, + TError, + TData, + TQueryFnData, + TQueryKey, + TPageParam +> +``` + +## Type Parameters + +• **TQueryFnData** + +• **TError** = `Error` + +• **TData** = `InfiniteData`\<`TQueryFnData`, `unknown`\> + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +## Parameters + +• **options**: [`CreateInfiniteQueryOptions`](../type-aliases/createinfinitequeryoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `TPageParam`\> + +## Returns + +[`CreateInfiniteQueryOptions`](../type-aliases/createinfinitequeryoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `TPageParam`\> + +## Defined in + +[packages/svelte-query/src/infiniteQueryOptions.ts:4](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/infiniteQueryOptions.ts#L4) diff --git a/docs/framework/svelte/reference/functions/queryoptions.md b/docs/framework/svelte/reference/functions/queryoptions.md new file mode 100644 index 0000000000..d499202669 --- /dev/null +++ b/docs/framework/svelte/reference/functions/queryoptions.md @@ -0,0 +1,66 @@ +--- +id: queryOptions +title: queryOptions +--- + +# Function: queryOptions() + +## queryOptions(options) + +```ts +function queryOptions( + options, +): DefinedInitialDataOptions & object +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`DefinedInitialDataOptions`](../type-aliases/definedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +### Returns + +[`DefinedInitialDataOptions`](../type-aliases/definedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` + +### Defined in + +[packages/svelte-query/src/queryOptions.ts:26](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/queryOptions.ts#L26) + +## queryOptions(options) + +```ts +function queryOptions( + options, +): UndefinedInitialDataOptions & object +``` + +### Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `Error` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +### Parameters + +• **options**: [`UndefinedInitialDataOptions`](../type-aliases/undefinedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +### Returns + +[`UndefinedInitialDataOptions`](../type-aliases/undefinedinitialdataoptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> & `object` + +### Defined in + +[packages/svelte-query/src/queryOptions.ts:37](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/queryOptions.ts#L37) diff --git a/docs/framework/svelte/reference/functions/setisrestoringcontext.md b/docs/framework/svelte/reference/functions/setisrestoringcontext.md new file mode 100644 index 0000000000..0ab290bf09 --- /dev/null +++ b/docs/framework/svelte/reference/functions/setisrestoringcontext.md @@ -0,0 +1,24 @@ +--- +id: setIsRestoringContext +title: setIsRestoringContext +--- + +# Function: setIsRestoringContext() + +```ts +function setIsRestoringContext(isRestoring): void +``` + +Sets a `isRestoring` on Svelte's context + +## Parameters + +• **isRestoring**: `Readable`\<`boolean`\> + +## Returns + +`void` + +## Defined in + +[packages/svelte-query/src/context.ts:40](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/context.ts#L40) diff --git a/docs/framework/svelte/reference/functions/setqueryclientcontext.md b/docs/framework/svelte/reference/functions/setqueryclientcontext.md new file mode 100644 index 0000000000..4a4ce300b2 --- /dev/null +++ b/docs/framework/svelte/reference/functions/setqueryclientcontext.md @@ -0,0 +1,24 @@ +--- +id: setQueryClientContext +title: setQueryClientContext +--- + +# Function: setQueryClientContext() + +```ts +function setQueryClientContext(client): void +``` + +Sets a QueryClient on Svelte's context + +## Parameters + +• **client**: `QueryClient` + +## Returns + +`void` + +## Defined in + +[packages/svelte-query/src/context.ts:21](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/context.ts#L21) diff --git a/docs/framework/svelte/reference/functions/usehydrate.md b/docs/framework/svelte/reference/functions/usehydrate.md new file mode 100644 index 0000000000..c4abb97e0d --- /dev/null +++ b/docs/framework/svelte/reference/functions/usehydrate.md @@ -0,0 +1,26 @@ +--- +id: useHydrate +title: useHydrate +--- + +# Function: useHydrate() + +```ts +function useHydrate(state?, options?, queryClient?): void +``` + +## Parameters + +• **state?**: `unknown` + +• **options?**: `HydrateOptions` + +• **queryClient?**: `QueryClient` + +## Returns + +`void` + +## Defined in + +[packages/svelte-query/src/useHydrate.ts:8](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useHydrate.ts#L8) diff --git a/docs/framework/svelte/reference/functions/useisfetching.md b/docs/framework/svelte/reference/functions/useisfetching.md new file mode 100644 index 0000000000..fbfd0d55bf --- /dev/null +++ b/docs/framework/svelte/reference/functions/useisfetching.md @@ -0,0 +1,24 @@ +--- +id: useIsFetching +title: useIsFetching +--- + +# Function: useIsFetching() + +```ts +function useIsFetching(filters?, queryClient?): Readable +``` + +## Parameters + +• **filters?**: `QueryFilters` + +• **queryClient?**: `QueryClient` + +## Returns + +`Readable`\<`number`\> + +## Defined in + +[packages/svelte-query/src/useIsFetching.ts:10](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useIsFetching.ts#L10) diff --git a/docs/framework/svelte/reference/functions/useismutating.md b/docs/framework/svelte/reference/functions/useismutating.md new file mode 100644 index 0000000000..2e05ae3218 --- /dev/null +++ b/docs/framework/svelte/reference/functions/useismutating.md @@ -0,0 +1,24 @@ +--- +id: useIsMutating +title: useIsMutating +--- + +# Function: useIsMutating() + +```ts +function useIsMutating(filters?, queryClient?): Readable +``` + +## Parameters + +• **filters?**: `MutationFilters` + +• **queryClient?**: `QueryClient` + +## Returns + +`Readable`\<`number`\> + +## Defined in + +[packages/svelte-query/src/useIsMutating.ts:10](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useIsMutating.ts#L10) diff --git a/docs/framework/svelte/reference/functions/useisrestoring.md b/docs/framework/svelte/reference/functions/useisrestoring.md new file mode 100644 index 0000000000..4cd72cfab8 --- /dev/null +++ b/docs/framework/svelte/reference/functions/useisrestoring.md @@ -0,0 +1,18 @@ +--- +id: useIsRestoring +title: useIsRestoring +--- + +# Function: useIsRestoring() + +```ts +function useIsRestoring(): Readable +``` + +## Returns + +`Readable`\<`boolean`\> + +## Defined in + +[packages/svelte-query/src/useIsRestoring.ts:4](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useIsRestoring.ts#L4) diff --git a/docs/framework/svelte/reference/functions/usemutationstate.md b/docs/framework/svelte/reference/functions/usemutationstate.md new file mode 100644 index 0000000000..83de5455e7 --- /dev/null +++ b/docs/framework/svelte/reference/functions/usemutationstate.md @@ -0,0 +1,28 @@ +--- +id: useMutationState +title: useMutationState +--- + +# Function: useMutationState() + +```ts +function useMutationState(options, queryClient?): Readable +``` + +## Type Parameters + +• **TResult** = `MutationState`\<`unknown`, `Error`, `unknown`, `unknown`\> + +## Parameters + +• **options**: [`MutationStateOptions`](../type-aliases/mutationstateoptions.md)\<`TResult`\> = `{}` + +• **queryClient?**: `QueryClient` + +## Returns + +`Readable`\<`TResult`[]\> + +## Defined in + +[packages/svelte-query/src/useMutationState.ts:24](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useMutationState.ts#L24) diff --git a/docs/framework/svelte/reference/functions/usequeryclient.md b/docs/framework/svelte/reference/functions/usequeryclient.md new file mode 100644 index 0000000000..e6f169c143 --- /dev/null +++ b/docs/framework/svelte/reference/functions/usequeryclient.md @@ -0,0 +1,22 @@ +--- +id: useQueryClient +title: useQueryClient +--- + +# Function: useQueryClient() + +```ts +function useQueryClient(queryClient?): QueryClient +``` + +## Parameters + +• **queryClient?**: `QueryClient` + +## Returns + +`QueryClient` + +## Defined in + +[packages/svelte-query/src/useQueryClient.ts:4](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/useQueryClient.ts#L4) diff --git a/docs/framework/svelte/reference/index.md b/docs/framework/svelte/reference/index.md new file mode 100644 index 0000000000..8b50592d89 --- /dev/null +++ b/docs/framework/svelte/reference/index.md @@ -0,0 +1,57 @@ +--- +id: '@tanstack/svelte-query' +title: '@tanstack/svelte-query' +--- + +# @tanstack/svelte-query + +## References + +### QueryClientProvider + +Renames and re-exports [HydrationBoundary](classes/hydrationboundary.md) + +## Classes + +- [HydrationBoundary](classes/hydrationboundary.md) + +## Type Aliases + +- [CreateBaseMutationResult](type-aliases/createbasemutationresult.md) +- [CreateBaseQueryOptions](type-aliases/createbasequeryoptions.md) +- [CreateBaseQueryResult](type-aliases/createbasequeryresult.md) +- [CreateInfiniteQueryOptions](type-aliases/createinfinitequeryoptions.md) +- [CreateInfiniteQueryResult](type-aliases/createinfinitequeryresult.md) +- [CreateMutateAsyncFunction](type-aliases/createmutateasyncfunction.md) +- [CreateMutateFunction](type-aliases/createmutatefunction.md) +- [CreateMutationOptions](type-aliases/createmutationoptions.md) +- [CreateMutationResult](type-aliases/createmutationresult.md) +- [CreateQueryOptions](type-aliases/createqueryoptions.md) +- [CreateQueryResult](type-aliases/createqueryresult.md) +- [DefinedCreateBaseQueryResult](type-aliases/definedcreatebasequeryresult.md) +- [DefinedCreateQueryResult](type-aliases/definedcreatequeryresult.md) +- [DefinedInitialDataOptions](type-aliases/definedinitialdataoptions.md) +- [MutationStateOptions](type-aliases/mutationstateoptions.md) +- [QueriesOptions](type-aliases/queriesoptions.md) +- [QueriesResults](type-aliases/queriesresults.md) +- [StoreOrVal](type-aliases/storeorval.md) +- [UndefinedInitialDataOptions](type-aliases/undefinedinitialdataoptions.md) + +## Functions + +- [createInfiniteQuery](functions/createinfinitequery.md) +- [createMutation](functions/createmutation.md) +- [createQueries](functions/createqueries.md) +- [createQuery](functions/createquery.md) +- [getIsRestoringContext](functions/getisrestoringcontext.md) +- [getQueryClientContext](functions/getqueryclientcontext.md) +- [infiniteQueryOptions](functions/infinitequeryoptions.md) +- [queryOptions](functions/queryoptions.md) +- [setIsRestoringContext](functions/setisrestoringcontext.md) +- [setQueryClientContext](functions/setqueryclientcontext.md) +- [useHydrate](functions/usehydrate.md) +- [useIsFetching](functions/useisfetching.md) +- [useIsMutating](functions/useismutating.md) +- [useIsRestoring](functions/useisrestoring.md) +- [useMutationState](functions/usemutationstate.md) +- [useQueryClient](functions/usequeryclient.md) diff --git a/docs/framework/svelte/reference/type-aliases/createbasemutationresult.md b/docs/framework/svelte/reference/type-aliases/createbasemutationresult.md new file mode 100644 index 0000000000..750c599d80 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createbasemutationresult.md @@ -0,0 +1,32 @@ +--- +id: CreateBaseMutationResult +title: CreateBaseMutationResult +--- + +# Type Alias: CreateBaseMutationResult\ + +```ts +type CreateBaseMutationResult: Override, object> & object; +``` + +## Type declaration + +### mutateAsync + +```ts +mutateAsync: CreateMutateAsyncFunction +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `unknown` + +• **TContext** = `unknown` + +## Defined in + +[packages/svelte-query/src/types.ts:113](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L113) diff --git a/docs/framework/svelte/reference/type-aliases/createbasequeryoptions.md b/docs/framework/svelte/reference/type-aliases/createbasequeryoptions.md new file mode 100644 index 0000000000..8a1967c124 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createbasequeryoptions.md @@ -0,0 +1,28 @@ +--- +id: CreateBaseQueryOptions +title: CreateBaseQueryOptions +--- + +# Type Alias: CreateBaseQueryOptions\ + +```ts +type CreateBaseQueryOptions: QueryObserverOptions; +``` + +Options for createBaseQuery + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[packages/svelte-query/src/types.ts:23](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L23) diff --git a/docs/framework/svelte/reference/type-aliases/createbasequeryresult.md b/docs/framework/svelte/reference/type-aliases/createbasequeryresult.md new file mode 100644 index 0000000000..01d19e64ea --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createbasequeryresult.md @@ -0,0 +1,22 @@ +--- +id: CreateBaseQueryResult +title: CreateBaseQueryResult +--- + +# Type Alias: CreateBaseQueryResult\ + +```ts +type CreateBaseQueryResult: Readable>; +``` + +Result from createBaseQuery + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[packages/svelte-query/src/types.ts:32](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L32) diff --git a/docs/framework/svelte/reference/type-aliases/createinfinitequeryoptions.md b/docs/framework/svelte/reference/type-aliases/createinfinitequeryoptions.md new file mode 100644 index 0000000000..e248532a85 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createinfinitequeryoptions.md @@ -0,0 +1,30 @@ +--- +id: CreateInfiniteQueryOptions +title: CreateInfiniteQueryOptions +--- + +# Type Alias: CreateInfiniteQueryOptions\ + +```ts +type CreateInfiniteQueryOptions: InfiniteQueryObserverOptions; +``` + +Options for createInfiniteQuery + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +• **TPageParam** = `unknown` + +## Defined in + +[packages/svelte-query/src/types.ts:52](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L52) diff --git a/docs/framework/svelte/reference/type-aliases/createinfinitequeryresult.md b/docs/framework/svelte/reference/type-aliases/createinfinitequeryresult.md new file mode 100644 index 0000000000..4027388adc --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createinfinitequeryresult.md @@ -0,0 +1,22 @@ +--- +id: CreateInfiniteQueryResult +title: CreateInfiniteQueryResult +--- + +# Type Alias: CreateInfiniteQueryResult\ + +```ts +type CreateInfiniteQueryResult: Readable>; +``` + +Result from createInfiniteQuery + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[packages/svelte-query/src/types.ts:69](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L69) diff --git a/docs/framework/svelte/reference/type-aliases/createmutateasyncfunction.md b/docs/framework/svelte/reference/type-aliases/createmutateasyncfunction.md new file mode 100644 index 0000000000..01567a772e --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createmutateasyncfunction.md @@ -0,0 +1,24 @@ +--- +id: CreateMutateAsyncFunction +title: CreateMutateAsyncFunction +--- + +# Type Alias: CreateMutateAsyncFunction\ + +```ts +type CreateMutateAsyncFunction: MutateFunction; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Defined in + +[packages/svelte-query/src/types.ts:106](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L106) diff --git a/docs/framework/svelte/reference/type-aliases/createmutatefunction.md b/docs/framework/svelte/reference/type-aliases/createmutatefunction.md new file mode 100644 index 0000000000..18230411ef --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createmutatefunction.md @@ -0,0 +1,32 @@ +--- +id: CreateMutateFunction +title: CreateMutateFunction +--- + +# Type Alias: CreateMutateFunction()\ + +```ts +type CreateMutateFunction: (...args) => void; +``` + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Parameters + +• ...**args**: `Parameters`\<`MutateFunction`\<`TData`, `TError`, `TVariables`, `TContext`\>\> + +## Returns + +`void` + +## Defined in + +[packages/svelte-query/src/types.ts:97](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L97) diff --git a/docs/framework/svelte/reference/type-aliases/createmutationoptions.md b/docs/framework/svelte/reference/type-aliases/createmutationoptions.md new file mode 100644 index 0000000000..c091bb44db --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createmutationoptions.md @@ -0,0 +1,26 @@ +--- +id: CreateMutationOptions +title: CreateMutationOptions +--- + +# Type Alias: CreateMutationOptions\ + +```ts +type CreateMutationOptions: OmitKeyof, "_defaulted">; +``` + +Options for createMutation + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `void` + +• **TContext** = `unknown` + +## Defined in + +[packages/svelte-query/src/types.ts:87](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L87) diff --git a/docs/framework/svelte/reference/type-aliases/createmutationresult.md b/docs/framework/svelte/reference/type-aliases/createmutationresult.md new file mode 100644 index 0000000000..f0cc9f62c7 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createmutationresult.md @@ -0,0 +1,26 @@ +--- +id: CreateMutationResult +title: CreateMutationResult +--- + +# Type Alias: CreateMutationResult\ + +```ts +type CreateMutationResult: Readable>; +``` + +Result from createMutation + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +• **TVariables** = `unknown` + +• **TContext** = `unknown` + +## Defined in + +[packages/svelte-query/src/types.ts:126](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L126) diff --git a/docs/framework/svelte/reference/type-aliases/createqueryoptions.md b/docs/framework/svelte/reference/type-aliases/createqueryoptions.md new file mode 100644 index 0000000000..0f24070104 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createqueryoptions.md @@ -0,0 +1,26 @@ +--- +id: CreateQueryOptions +title: CreateQueryOptions +--- + +# Type Alias: CreateQueryOptions\ + +```ts +type CreateQueryOptions: CreateBaseQueryOptions; +``` + +Options for createQuery + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[packages/svelte-query/src/types.ts:38](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L38) diff --git a/docs/framework/svelte/reference/type-aliases/createqueryresult.md b/docs/framework/svelte/reference/type-aliases/createqueryresult.md new file mode 100644 index 0000000000..f57f253fea --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/createqueryresult.md @@ -0,0 +1,22 @@ +--- +id: CreateQueryResult +title: CreateQueryResult +--- + +# Type Alias: CreateQueryResult\ + +```ts +type CreateQueryResult: CreateBaseQueryResult; +``` + +Result from createQuery + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[packages/svelte-query/src/types.ts:46](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L46) diff --git a/docs/framework/svelte/reference/type-aliases/definedcreatebasequeryresult.md b/docs/framework/svelte/reference/type-aliases/definedcreatebasequeryresult.md new file mode 100644 index 0000000000..1c4afda88a --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/definedcreatebasequeryresult.md @@ -0,0 +1,22 @@ +--- +id: DefinedCreateBaseQueryResult +title: DefinedCreateBaseQueryResult +--- + +# Type Alias: DefinedCreateBaseQueryResult\ + +```ts +type DefinedCreateBaseQueryResult: Readable>; +``` + +Options for createBaseQuery with initialData + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[packages/svelte-query/src/types.ts:75](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L75) diff --git a/docs/framework/svelte/reference/type-aliases/definedcreatequeryresult.md b/docs/framework/svelte/reference/type-aliases/definedcreatequeryresult.md new file mode 100644 index 0000000000..7f360dc680 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/definedcreatequeryresult.md @@ -0,0 +1,22 @@ +--- +id: DefinedCreateQueryResult +title: DefinedCreateQueryResult +--- + +# Type Alias: DefinedCreateQueryResult\ + +```ts +type DefinedCreateQueryResult: DefinedCreateBaseQueryResult; +``` + +Options for createQuery with initialData + +## Type Parameters + +• **TData** = `unknown` + +• **TError** = `DefaultError` + +## Defined in + +[packages/svelte-query/src/types.ts:81](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L81) diff --git a/docs/framework/svelte/reference/type-aliases/definedinitialdataoptions.md b/docs/framework/svelte/reference/type-aliases/definedinitialdataoptions.md new file mode 100644 index 0000000000..95a0613537 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/definedinitialdataoptions.md @@ -0,0 +1,32 @@ +--- +id: DefinedInitialDataOptions +title: DefinedInitialDataOptions +--- + +# Type Alias: DefinedInitialDataOptions\ + +```ts +type DefinedInitialDataOptions: CreateQueryOptions & object; +``` + +## Type declaration + +### initialData + +```ts +initialData: NonUndefinedGuard | () => NonUndefinedGuard; +``` + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[packages/svelte-query/src/queryOptions.ts:15](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/queryOptions.ts#L15) diff --git a/docs/framework/svelte/reference/type-aliases/mutationstateoptions.md b/docs/framework/svelte/reference/type-aliases/mutationstateoptions.md new file mode 100644 index 0000000000..ecbdaad703 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/mutationstateoptions.md @@ -0,0 +1,42 @@ +--- +id: MutationStateOptions +title: MutationStateOptions +--- + +# Type Alias: MutationStateOptions\ + +```ts +type MutationStateOptions: object; +``` + +Options for useMutationState + +## Type Parameters + +• **TResult** = `MutationState` + +## Type declaration + +### filters? + +```ts +optional filters: MutationFilters; +``` + +### select()? + +```ts +optional select: (mutation) => TResult; +``` + +#### Parameters + +• **mutation**: `Mutation`\<`unknown`, `DefaultError`, `unknown`, `unknown`\> + +#### Returns + +`TResult` + +## Defined in + +[packages/svelte-query/src/types.ts:140](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L140) diff --git a/docs/framework/svelte/reference/type-aliases/queriesoptions.md b/docs/framework/svelte/reference/type-aliases/queriesoptions.md new file mode 100644 index 0000000000..0f6fe1097b --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/queriesoptions.md @@ -0,0 +1,24 @@ +--- +id: QueriesOptions +title: QueriesOptions +--- + +# Type Alias: QueriesOptions\ + +```ts +type QueriesOptions: TDepth["length"] extends MAXIMUM_DEPTH ? QueryObserverOptionsForCreateQueries[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetQueryObserverOptionsForCreateQueries] : T extends [infer Head, ...(infer Tails)] ? QueriesOptions<[...Tails], [...TResults, GetQueryObserverOptionsForCreateQueries], [...TDepth, 1]> : ReadonlyArray extends T ? T : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverOptionsForCreateQueries[] : QueryObserverOptionsForCreateQueries[]; +``` + +QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TResults** _extends_ `any`[] = [] + +• **TDepth** _extends_ `ReadonlyArray`\<`number`\> = [] + +## Defined in + +[packages/svelte-query/src/createQueries.ts:129](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQueries.ts#L129) diff --git a/docs/framework/svelte/reference/type-aliases/queriesresults.md b/docs/framework/svelte/reference/type-aliases/queriesresults.md new file mode 100644 index 0000000000..7ce41d896f --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/queriesresults.md @@ -0,0 +1,24 @@ +--- +id: QueriesResults +title: QueriesResults +--- + +# Type Alias: QueriesResults\ + +```ts +type QueriesResults: TDepth["length"] extends MAXIMUM_DEPTH ? QueryObserverResult[] : T extends [] ? [] : T extends [infer Head] ? [...TResults, GetCreateQueryResult] : T extends [infer Head, ...(infer Tails)] ? QueriesResults<[...Tails], [...TResults, GetCreateQueryResult], [...TDepth, 1]> : T extends QueryObserverOptionsForCreateQueries[] ? QueryObserverResult[] : QueryObserverResult[]; +``` + +QueriesResults reducer recursively maps type param to results + +## Type Parameters + +• **T** _extends_ `any`[] + +• **TResults** _extends_ `any`[] = [] + +• **TDepth** _extends_ `ReadonlyArray`\<`number`\> = [] + +## Defined in + +[packages/svelte-query/src/createQueries.ts:171](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/createQueries.ts#L171) diff --git a/docs/framework/svelte/reference/type-aliases/storeorval.md b/docs/framework/svelte/reference/type-aliases/storeorval.md new file mode 100644 index 0000000000..7f7c5d5125 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/storeorval.md @@ -0,0 +1,20 @@ +--- +id: StoreOrVal +title: StoreOrVal +--- + +# Type Alias: StoreOrVal\ + +```ts +type StoreOrVal: T | Readable; +``` + +Allows a type to be either the base object or a store of that object + +## Type Parameters + +• **T** + +## Defined in + +[packages/svelte-query/src/types.ts:20](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/types.ts#L20) diff --git a/docs/framework/svelte/reference/type-aliases/undefinedinitialdataoptions.md b/docs/framework/svelte/reference/type-aliases/undefinedinitialdataoptions.md new file mode 100644 index 0000000000..de13b3d802 --- /dev/null +++ b/docs/framework/svelte/reference/type-aliases/undefinedinitialdataoptions.md @@ -0,0 +1,32 @@ +--- +id: UndefinedInitialDataOptions +title: UndefinedInitialDataOptions +--- + +# Type Alias: UndefinedInitialDataOptions\ + +```ts +type UndefinedInitialDataOptions: CreateQueryOptions & object; +``` + +## Type declaration + +### initialData? + +```ts +optional initialData: undefined; +``` + +## Type Parameters + +• **TQueryFnData** = `unknown` + +• **TError** = `DefaultError` + +• **TData** = `TQueryFnData` + +• **TQueryKey** _extends_ `QueryKey` = `QueryKey` + +## Defined in + +[packages/svelte-query/src/queryOptions.ts:4](https://github.com/TanStack/query/blob/dac5da5416b82b0be38a8fb34dde1fc6670f0a59/packages/svelte-query/src/queryOptions.ts#L4) diff --git a/docs/framework/vue/community/community-projects.md b/docs/framework/vue/community/community-projects.md index 86e065967f..8c3fbed616 100644 --- a/docs/framework/vue/community/community-projects.md +++ b/docs/framework/vue/community/community-projects.md @@ -1,5 +1,20 @@ --- id: community-projects title: Community Projects -ref: docs/framework/react/community/community-projects.md --- + +There are lots of community projects that build on top of Vue Query and use it to provide additional functionality or enhanced developer experience. Projects are listed in alphabetical order. If you have a project that you would like to add to this list, please open a PR! + +> Please note that these projects are entirely community maintained. If you have questions about these projects, please reach out to the project maintainers. + +## Query Key factory + +A library for creating typesafe standardized query keys, useful for cache management in `@tanstack/query` + +Link: https://github.com/lukemorales/query-key-factory + +## Query Rewind + +Time travel and visualize state during development + +Link: https://reactqueryrewind.com/ diff --git a/docs/framework/vue/community/lukemorales-query-key-factory.md b/docs/framework/vue/community/lukemorales-query-key-factory.md deleted file mode 100644 index 800a06f5b5..0000000000 --- a/docs/framework/vue/community/lukemorales-query-key-factory.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -id: query-key-factory -title: Query Key Factory ---- - -## Query Key Factory - -A library for creating typesafe standardized query keys, useful for cache management in `@tanstack/query` - -Link: https://github.com/lukemorales/query-key-factory diff --git a/docs/framework/vue/devtools.md b/docs/framework/vue/devtools.md index 44e17bd9fa..a58aa9995a 100644 --- a/docs/framework/vue/devtools.md +++ b/docs/framework/vue/devtools.md @@ -7,15 +7,10 @@ Wave your hands in the air and shout hooray because Vue Query comes with dedicat When you begin your Vue Query journey, you'll want these devtools by your side. They help visualize all of the inner workings of Vue Query and will likely save you hours of debugging if you find yourself in a pinch! -The only thing you need to do is to install the official **[Vue Devtools](https://devtools.vuejs.org/guide/installation.html)**. - -Vue Query will seamlessly integrate with the official devtools, adding custom inspector and timeline events. -Devtool code will be treeshaken from production bundles by default. - ## Component based Devtools (Vue 3) -You can embeed devtools component into your page by using dedicated package. -Component based devtools are using the same framework-agnostic implementation, have more features and are updated more frequently. +You can directly integrate the devtools component into your page using a dedicated package. +Component-based devtools use a framework-agnostic implementation and are always up-to-date. The devtools component is a separate package that you need to install: @@ -49,19 +44,34 @@ import { VueQueryDevtools } from '@tanstack/vue-query-devtools' ### Options - `initialIsOpen: Boolean` - - Set this `true` if you want the dev tools to default to being open + - Set this `true` if you want the dev tools to default to being open. - `buttonPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right"` - - Defaults to `bottom-right` - - The position of the React Query logo to open and close the devtools panel + - Defaults to `bottom-right`. + - The position of the React Query logo to open and close the devtools panel. - `position?: "top" | "bottom" | "left" | "right"` - - Defaults to `bottom` - - The position of the React Query devtools panel -- `client?: QueryClient`, + - Defaults to `bottom`. + - The position of the React Query devtools panel. +- `client?: QueryClient` - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used. - `errorTypes?: { name: string; initializer: (query: Query) => TError}` - - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error. + - Use this to predefine some errors that can be triggered on your queries. The initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error. - `styleNonce?: string` - Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. - `shadowDOMTarget?: ShadowRoot` - Default behavior will apply the devtool's styles to the head tag within the DOM. - - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instad of within the head tag in the light DOM. + - Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM. + +## Traditional Devtools + +Vue Query will seamlessly integrate with the [Official Vue devtools](https://github.com/vuejs/devtools-next), adding custom inspector and timeline events. +Devtool code will be treeshaken from production bundles by default. + +To make it work, you only need to enable it in the plugin options: + +```ts +app.use(VueQueryPlugin, { + enableDevtoolsV6Plugin: true, +}) +``` + +Both v6 and v7 versions of devtools are supported. diff --git a/docs/framework/vue/guides/disabling-queries.md b/docs/framework/vue/guides/disabling-queries.md index bd0de7532f..11c0e1c8f2 100644 --- a/docs/framework/vue/guides/disabling-queries.md +++ b/docs/framework/vue/guides/disabling-queries.md @@ -60,11 +60,13 @@ const { data } = useQuery({ import { useQuery, skipToken } from '@tanstack/vue-query' const filter = ref('') -const isEnabled = computed(() => !!filter.value) +const queryFn = computed(() => + !!filter.value ? () => fetchTodos(filter) : skipToken, +) const { data } = useQuery({ queryKey: ['todos', filter], // ⬇️ disabled as long as the filter is undefined or empty - queryFn: filter ? () => fetchTodos(filter) : skipToken, + queryFn: queryFn, }) diff --git a/docs/framework/vue/guides/optimistic-updates.md b/docs/framework/vue/guides/optimistic-updates.md index 57a25aeba8..be3d9cf549 100644 --- a/docs/framework/vue/guides/optimistic-updates.md +++ b/docs/framework/vue/guides/optimistic-updates.md @@ -2,102 +2,5 @@ id: optimistic-updates title: Optimistic Updates ref: docs/framework/react/guides/optimistic-updates.md +replace: { 'React': 'Vue' } --- - -When you optimistically update your state before performing a mutation, there is a chance that the mutation will fail. In most of these failure cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update. - -To do this, `useMutation`'s `onMutate` handler option allows you to return a value that will later be passed to both `onError` and `onSettled` handlers as the last argument. In most cases, it is most useful to pass a rollback function. - -## Updating a list of todos when adding a new todo - -[//]: # 'Example' - -```tsx -const queryClient = useQueryClient() - -useMutation({ - mutationFn: updateTodo, - // When mutate is called: - onMutate: async (newTodo) => { - // Cancel any outgoing refetches - // (so they don't overwrite our optimistic update) - await queryClient.cancelQueries({ queryKey: ['todos'] }) - - // Snapshot the previous value - const previousTodos = queryClient.getQueryData(['todos']) - - // Optimistically update to the new value - queryClient.setQueryData(['todos'], (old) => [...old, newTodo]) - - // Return a context object with the snapshotted value - return { previousTodos } - }, - // If the mutation fails, - // use the context returned from onMutate to roll back - onError: (err, newTodo, context) => { - queryClient.setQueryData(['todos'], context.previousTodos) - }, - // Always refetch after error or success: - onSettled: () => { - queryClient.invalidateQueries({ queryKey: ['todos'] }) - }, -}) -``` - -[//]: # 'Example' - -## Updating a single todo - -[//]: # 'Example2' - -```tsx -useMutation({ - mutationFn: updateTodo, - // When mutate is called: - onMutate: async (newTodo) => { - // Cancel any outgoing refetches - // (so they don't overwrite our optimistic update) - await queryClient.cancelQueries({ queryKey: ['todos', newTodo.id] }) - - // Snapshot the previous value - const previousTodo = queryClient.getQueryData(['todos', newTodo.id]) - - // Optimistically update to the new value - queryClient.setQueryData(['todos', newTodo.id], newTodo) - - // Return a context with the previous and new todo - return { previousTodo, newTodo } - }, - // If the mutation fails, use the context we returned above - onError: (err, newTodo, context) => { - queryClient.setQueryData( - ['todos', context.newTodo.id], - context.previousTodo, - ) - }, - // Always refetch after error or success: - onSettled: (newTodo) => { - queryClient.invalidateQueries({ queryKey: ['todos', newTodo.id] }) - }, -}) -``` - -[//]: # 'Example2' - -You can also use the `onSettled` function in place of the separate `onError` and `onSuccess` handlers if you wish: - -[//]: # 'Example3' - -```tsx -useMutation({ - mutationFn: updateTodo, - // ... - onSettled: (newTodo, error, variables, context) => { - if (error) { - // do something - } - }, -}) -``` - -[//]: # 'Example3' diff --git a/docs/framework/vue/guides/query-options.md b/docs/framework/vue/guides/query-options.md index 83bcf1e853..f2bb35eac6 100644 --- a/docs/framework/vue/guides/query-options.md +++ b/docs/framework/vue/guides/query-options.md @@ -2,4 +2,5 @@ id: query-options title: Query Options ref: docs/framework/react/guides/query-options.md +replace: { '@tanstack/react-query': '@tanstack/vue-query' } --- diff --git a/docs/framework/vue/installation.md b/docs/framework/vue/installation.md index 1386b79fc4..1bb28b1b66 100644 --- a/docs/framework/vue/installation.md +++ b/docs/framework/vue/installation.md @@ -5,18 +5,16 @@ title: Installation You can install Vue Query via [NPM](https://npmjs.com). -> v5 is currently available as a release-candidate. We don't anticipate any major API changes from here on out. We encourage you to try it out and report any issues you find. - ### NPM ```bash -$ npm i @tanstack/vue-query +npm i @tanstack/vue-query # or -$ pnpm add @tanstack/vue-query +pnpm add @tanstack/vue-query # or -$ yarn add @tanstack/vue-query +yarn add @tanstack/vue-query # or -$ bun add @tanstack/vue-query +bun add @tanstack/vue-query ``` > Wanna give it a spin before you download? Try out the [basic](../examples/basic) example! diff --git a/docs/framework/vue/plugins/broadcastQueryClient.md b/docs/framework/vue/plugins/broadcastQueryClient.md new file mode 100644 index 0000000000..a4cfe04bc6 --- /dev/null +++ b/docs/framework/vue/plugins/broadcastQueryClient.md @@ -0,0 +1,6 @@ +--- +id: broadcastQueryClient +title: broadcastQueryClient (Experimental) +ref: docs/framework/react/plugins/broadcastQueryClient.md +replace: { 'react-query': 'vue-query' } +--- diff --git a/docs/framework/vue/plugins/createPersister.md b/docs/framework/vue/plugins/createPersister.md new file mode 100644 index 0000000000..b2f9773ca8 --- /dev/null +++ b/docs/framework/vue/plugins/createPersister.md @@ -0,0 +1,131 @@ +--- +id: createPersister +title: experimental_createPersister +--- + +## Installation + +This utility comes as a separate package and is available under the `'@tanstack/query-persist-client-core'` import. + +```bash +npm install @tanstack/query-persist-client-core +``` + +or + +```bash +pnpm add @tanstack/query-persist-client-core +``` + +or + +```bash +yarn add @tanstack/query-persist-client-core +``` + +or + +```bash +bun add @tanstack/query-persist-client-core +``` + +## Usage + +- Import the `experimental_createPersister` function +- Create a new `experimental_createPersister` + - you can pass any `storage` to it that adheres to the `AsyncStorage` or `Storage` interface +- Pass that `persister` as an option to your Query. This can be done either by passing it to the `defaultOptions` of the `QueryClient` or to any `useQuery` hook instance. + - If you pass this `persister` as `defaultOptions`, all queries will be persisted to the provided `storage`. You can additionally narrow this down by passing `filters`. In contrast to the `persistClient` plugin, this will not persist the whole query client as a single item, but each query separately. As a key, the query hash is used. + - If you provide this `persister` to a single `useQuery` hook, only this Query will be persisted. + +This way, you do not need to store whole `QueryClient`, but choose what is worth to be persisted in your application. Each query is lazily restored (when the Query is first used) and persisted (after each run of the `queryFn`), so it does not need to be throttled. `staleTime` is also respected after restoring the Query, so if data is considered `stale`, it will be refetched immediately after restoring. If data is `fresh`, the `queryFn` will not run. + +Garbage collecting a Query from memory **does not** affect the persisted data. That means Queries can be kept in memory for a shorter period of time to be more **memory efficient**. If they are used the next time, they will just be restored from the persistent storage again. + +```tsx +import { QueryClient } from '@tanstack/vue-query' +import { experimental_createPersister } from '@tanstack/query-persist-client-core' + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + gcTime: 1000 * 30, // 30 seconds + persister: experimental_createPersister({ + storage: localStorage, + maxAge: 1000 * 60 * 60 * 12, // 12 hours + }), + }, + }, +}) +``` + +### Adapted defaults + +The `createPersister` plugin technically wraps the `queryFn`, so it doesn't restore if the `queryFn` doesn't run. In that way, it acts as a caching layer between the Query and the network. Thus, the `networkMode` defaults to `'offlineFirst'` when a persister is used, so that restoring from the persistent storage can also happen even if there is no network connection. + +## API + +### `experimental_createPersister` + +```tsx +experimental_createPersister(options: StoragePersisterOptions) +``` + +#### `Options` + +```tsx +export interface StoragePersisterOptions { + /** The storage client used for setting and retrieving items from cache. + * For SSR pass in `undefined`. + */ + storage: AsyncStorage | Storage | undefined | null + /** + * How to serialize the data to storage. + * @default `JSON.stringify` + */ + serialize?: (persistedQuery: PersistedQuery) => string + /** + * How to deserialize the data from storage. + * @default `JSON.parse` + */ + deserialize?: (cachedString: string) => PersistedQuery + /** + * A unique string that can be used to forcefully invalidate existing caches, + * if they do not share the same buster string + */ + buster?: string + /** + * The max-allowed age of the cache in milliseconds. + * If a persisted cache is found that is older than this + * time, it will be discarded + * @default 24 hours + */ + maxAge?: number + /** + * Prefix to be used for storage key. + * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`. + */ + prefix?: string + /** + * Filters to narrow down which Queries should be persisted. + */ + filters?: QueryFilters +} + +interface AsyncStorage { + getItem: (key: string) => Promise + setItem: (key: string, value: string) => Promise + removeItem: (key: string) => Promise +} +``` + +The default options are: + +```tsx +{ + prefix = 'tanstack-query', + maxAge = 1000 * 60 * 60 * 24, + serialize = JSON.stringify, + deserialize = JSON.parse, +} +``` diff --git a/docs/framework/vue/reference/hydration.md b/docs/framework/vue/reference/hydration.md index 74e94770d6..f4955994b2 100644 --- a/docs/framework/vue/reference/hydration.md +++ b/docs/framework/vue/reference/hydration.md @@ -5,7 +5,5 @@ ref: docs/framework/react/reference/hydration.md replace: { '@tanstack/react-query': '@tanstack/vue-query' } --- -[//]: # 'useHydrate' -[//]: # 'useHydrate' -[//]: # 'Hydrate' -[//]: # 'Hydrate' +[//]: # 'HydrationBoundary' +[//]: # 'HydrationBoundary' diff --git a/docs/framework/vue/reference/infiniteQueryOptions.md b/docs/framework/vue/reference/infiniteQueryOptions.md new file mode 100644 index 0000000000..fa4b38aae9 --- /dev/null +++ b/docs/framework/vue/reference/infiniteQueryOptions.md @@ -0,0 +1,5 @@ +--- +id: infiniteQueryOptions +title: infiniteQueryOptions +ref: docs/framework/react/reference/infiniteQueryOptions.md +--- diff --git a/docs/framework/vue/typescript.md b/docs/framework/vue/typescript.md index 71b354a0e4..731c276a24 100644 --- a/docs/framework/vue/typescript.md +++ b/docs/framework/vue/typescript.md @@ -3,7 +3,11 @@ id: typescript title: TypeScript ref: docs/framework/react/typescript.md replace: - { 'React': 'Vue', 'react-query package version': 'vue-query package version' } + { + 'React': 'Vue', + '@tanstack/react-query': '@tanstack/vue-query', + 'react-query package version': 'vue-query package version', + } --- [//]: # 'TypeInference1' @@ -86,6 +90,8 @@ if (error.value instanceof Error) { [//]: # 'TypingError3' [//]: # 'RegisterErrorType' [//]: # 'RegisterErrorType' +[//]: # 'TypingMeta' +[//]: # 'TypingMeta' [//]: # 'TypingQueryOptions' [//]: # 'TypingQueryOptions' [//]: # 'Materials' diff --git a/docs/reference/QueryClient.md b/docs/reference/QueryClient.md index d7e1a25442..2f11f7f6c6 100644 --- a/docs/reference/QueryClient.md +++ b/docs/reference/QueryClient.md @@ -62,6 +62,7 @@ Its available methods are: - `defaultOptions?: DefaultOptions` - Optional - Define defaults for all queries and mutations using this queryClient. + - You can also define defaults to be used for [hydration](../../framework/react/reference/hydration) ## `queryClient.fetchQuery` diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..98d195e26c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,43 @@ +// @ts-check + +// @ts-ignore Needed due to moduleResolution Node vs Bundler +import { tanstackConfig } from '@tanstack/config/eslint' +import pluginCspell from '@cspell/eslint-plugin' + +export default [ + ...tanstackConfig, + { + name: 'tanstack/temp', + plugins: { + cspell: pluginCspell, + }, + rules: { + 'cspell/spellchecker': [ + 'warn', + { + cspell: { + words: [ + 'codemod', // We support our codemod + 'extralight', // Our public interface + 'jscodeshift', + 'Promisable', // Our public interface + 'retryer', // Our public interface + 'solidjs', // Our target framework + 'tabular-nums', // https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric + 'tanstack', // Our package scope + 'todos', // Too general word to be caught as error + 'TSES', // @typescript-eslint package's interface + 'tsqd', // Our public interface (TanStack Query Devtools shorthand) + 'tsup', // We use tsup as builder + 'typecheck', // Field of vite.config.ts + 'vue-demi', // dependency of @tanstack/vue-query + ], + }, + }, + ], + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-empty-function': 'off', + 'no-case-declarations': 'off', + }, + }, +] diff --git a/examples/angular/basic/package.json b/examples/angular/basic/package.json index 1e5321cbbc..b726df8ac3 100644 --- a/examples/angular/basic/package.json +++ b/examples/angular/basic/package.json @@ -9,24 +9,21 @@ }, "private": true, "dependencies": { - "@angular/animations": "^17.3.3", - "@angular/common": "^17.3.3", - "@angular/compiler": "^17.3.3", - "@angular/core": "^17.3.3", - "@angular/forms": "^17.3.3", - "@angular/platform-browser": "^17.3.3", - "@angular/platform-browser-dynamic": "^17.3.3", - "@angular/router": "^17.3.3", - "@tanstack/angular-query-experimental": "^5.35.3", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@tanstack/angular-query-experimental": "^5.51.17", "rxjs": "^7.8.1", - "tslib": "^2.6.2", - "zone.js": "^0.14.4" + "tslib": "^2.6.3", + "zone.js": "^0.14.8" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.3", - "@angular/cli": "^17.3.3", - "@angular/compiler-cli": "^17.3.3", - "@tanstack/angular-query-devtools-experimental": "^5.35.3", - "typescript": "5.2.2" + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.12", + "@tanstack/angular-query-devtools-experimental": "^5.51.17", + "typescript": "5.3.3" } } diff --git a/examples/angular/basic/src/app/components/posts.component.html b/examples/angular/basic/src/app/components/posts.component.html index 779b30d0ea..568a6a4df4 100644 --- a/examples/angular/basic/src/app/components/posts.component.html +++ b/examples/angular/basic/src/app/components/posts.component.html @@ -20,7 +20,7 @@

Posts

queryClient.getQueryData(['post', post.id]) ? { fontWeight: 'bold', - color: 'green' + color: 'green', } : {} " diff --git a/examples/angular/infinite-query-with-max-pages/package.json b/examples/angular/infinite-query-with-max-pages/package.json index df1fd1ac0f..38d0a912e7 100644 --- a/examples/angular/infinite-query-with-max-pages/package.json +++ b/examples/angular/infinite-query-with-max-pages/package.json @@ -1,32 +1,29 @@ { "name": "@tanstack/query-example-angular-infinite-query-with-max-pages", - "version": "0.0.0", + "private": true, + "type": "module", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "watch": "ng build --watch --configuration development" }, - "private": true, "dependencies": { - "@angular/animations": "^17.3.3", - "@angular/common": "^17.3.3", - "@angular/compiler": "^17.3.3", - "@angular/core": "^17.3.3", - "@angular/forms": "^17.3.3", - "@angular/platform-browser": "^17.3.3", - "@angular/platform-browser-dynamic": "^17.3.3", - "@angular/router": "^17.3.3", - "@tanstack/angular-query-experimental": "^5.35.3", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@tanstack/angular-query-experimental": "^5.51.17", "rxjs": "^7.8.1", - "tslib": "^2.6.2", - "zone.js": "^0.14.4" + "tslib": "^2.6.3", + "zone.js": "^0.14.8" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.3", - "@angular/cli": "^17.3.3", - "@angular/compiler-cli": "^17.3.3", - "@tanstack/angular-query-devtools-experimental": "^5.35.3", - "typescript": "5.2.2" + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.12", + "@tanstack/angular-query-devtools-experimental": "^5.51.17", + "typescript": "5.3.3" } } diff --git a/examples/angular/router/package.json b/examples/angular/router/package.json index 7b0c521fe9..27ae67e197 100644 --- a/examples/angular/router/package.json +++ b/examples/angular/router/package.json @@ -9,24 +9,22 @@ }, "private": true, "dependencies": { - "@angular/animations": "^17.3.3", - "@angular/common": "^17.3.3", - "@angular/compiler": "^17.3.3", - "@angular/core": "^17.3.3", - "@angular/forms": "^17.3.3", - "@angular/platform-browser": "^17.3.3", - "@angular/platform-browser-dynamic": "^17.3.3", - "@angular/router": "^17.3.3", - "@tanstack/angular-query-experimental": "^5.35.3", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@angular/router": "^17.3.12", + "@tanstack/angular-query-experimental": "^5.51.17", "rxjs": "^7.8.1", - "tslib": "^2.6.2", - "zone.js": "^0.14.4" + "tslib": "^2.6.3", + "zone.js": "^0.14.8" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.3", - "@angular/cli": "^17.3.3", - "@angular/compiler-cli": "^17.3.3", - "@tanstack/angular-query-devtools-experimental": "^5.35.3", - "typescript": "5.2.2" + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.12", + "@tanstack/angular-query-devtools-experimental": "^5.51.17", + "typescript": "5.3.3" } } diff --git a/examples/angular/router/src/app/components/posts.component.html b/examples/angular/router/src/app/components/posts.component.html index b23dffb214..06f7252914 100644 --- a/examples/angular/router/src/app/components/posts.component.html +++ b/examples/angular/router/src/app/components/posts.component.html @@ -19,7 +19,7 @@

Posts

queryClient.getQueryData(['post', post.id]) ? { fontWeight: 'bold', - color: 'green' + color: 'green', } : {} " diff --git a/examples/angular/simple/package.json b/examples/angular/simple/package.json index 2fbce9c4d2..b1206b6ae6 100644 --- a/examples/angular/simple/package.json +++ b/examples/angular/simple/package.json @@ -9,24 +9,22 @@ }, "private": true, "dependencies": { - "@angular/animations": "^17.3.3", - "@angular/common": "^17.3.3", - "@angular/compiler": "^17.3.3", - "@angular/core": "^17.3.3", - "@angular/forms": "^17.3.3", - "@angular/platform-browser": "^17.3.3", - "@angular/platform-browser-dynamic": "^17.3.3", - "@angular/router": "^17.3.3", - "@tanstack/angular-query-experimental": "^5.35.3", + "@angular/common": "^17.3.12", + "@angular/compiler": "^17.3.12", + "@angular/core": "^17.3.12", + "@angular/platform-browser": "^17.3.12", + "@angular/platform-browser-dynamic": "^17.3.12", + "@angular/router": "^17.3.12", + "@tanstack/angular-query-experimental": "^5.51.17", "rxjs": "^7.8.1", - "tslib": "^2.6.2", - "zone.js": "^0.14.4" + "tslib": "^2.6.3", + "zone.js": "^0.14.8" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.3", - "@angular/cli": "^17.3.3", - "@angular/compiler-cli": "^17.3.3", - "@tanstack/angular-query-devtools-experimental": "^5.35.3", - "typescript": "5.2.2" + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.12", + "@tanstack/angular-query-devtools-experimental": "^5.51.17", + "typescript": "5.3.3" } } diff --git a/examples/react/algolia/package.json b/examples/react/algolia/package.json index a167937636..6dbdb2a338 100644 --- a/examples/react/algolia/package.json +++ b/examples/react/algolia/package.json @@ -9,32 +9,20 @@ "test:types": "tsc" }, "dependencies": { - "@algolia/client-search": "4.22.1", - "@algolia/transporter": "4.22.1", - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "algoliasearch": "4.22.1", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "algoliasearch": "4.24.0", + "react": "19.0.0-rc-4c2e457c7c-20240522", + "react-dom": "19.0.0-rc-4c2e457c7c-20240522" }, "devDependencies": { - "@tanstack/eslint-plugin-query": "^5.32.1", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", - "@vitejs/plugin-react": "^4.2.1", - "typescript": "5.2.2", - "vite": "^5.1.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "@tanstack/eslint-plugin-query": "^5.51.15", + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "@vitejs/plugin-react": "^4.3.1", + "typescript": "5.3.3", + "vite": "^5.3.5" } } diff --git a/examples/react/algolia/tsconfig.json b/examples/react/algolia/tsconfig.json index 6d545f543f..7c962d9747 100644 --- a/examples/react/algolia/tsconfig.json +++ b/examples/react/algolia/tsconfig.json @@ -7,7 +7,7 @@ "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "bundler", + "moduleResolution": "Bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, diff --git a/examples/react/auto-refetching/next-env.d.ts b/examples/react/auto-refetching/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/react/auto-refetching/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/react/auto-refetching/next.config.js b/examples/react/auto-refetching/next.config.js index 954704d28c..033754658c 100644 --- a/examples/react/auto-refetching/next.config.js +++ b/examples/react/auto-refetching/next.config.js @@ -1,5 +1,13 @@ -module.exports = { +// @ts-check + +/** @type {import('next').NextConfig} */ +const nextConfig = { eslint: { ignoreDuringBuilds: true, }, + typescript: { + ignoreBuildErrors: true, + }, } + +export default nextConfig diff --git a/examples/react/auto-refetching/package.json b/examples/react/auto-refetching/package.json index 492afea6a0..15371e2987 100644 --- a/examples/react/auto-refetching/package.json +++ b/examples/react/auto-refetching/package.json @@ -1,18 +1,22 @@ { "name": "@tanstack/query-example-react-auto-refetching", "private": true, + "type": "module", "scripts": { "dev": "next", "build": "next build", "start": "next start" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "axios": "^1.6.7", - "isomorphic-unfetch": "4.0.2", - "next": "^14.0.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "next": "^14.2.5", "react": "^18.2.0", "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "typescript": "5.3.3" } } diff --git a/examples/react/auto-refetching/src/pages/api/data.js b/examples/react/auto-refetching/src/pages/api/data.ts similarity index 67% rename from examples/react/auto-refetching/src/pages/api/data.js rename to examples/react/auto-refetching/src/pages/api/data.ts index 9c0cb35897..57faeb3916 100644 --- a/examples/react/auto-refetching/src/pages/api/data.js +++ b/examples/react/auto-refetching/src/pages/api/data.ts @@ -1,7 +1,12 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + // an simple endpoint for getting current list let list = ['Item 1', 'Item 2', 'Item 3'] -export default async (req, res) => { +export default async ( + req: NextApiRequest, + res: NextApiResponse, +) => { if (req.query.add) { if (!list.includes(req.query.add)) { list.push(req.query.add) diff --git a/examples/react/auto-refetching/src/pages/index.js b/examples/react/auto-refetching/src/pages/index.tsx similarity index 91% rename from examples/react/auto-refetching/src/pages/index.js rename to examples/react/auto-refetching/src/pages/index.tsx index 09831ec7d8..470a6e78fa 100644 --- a/examples/react/auto-refetching/src/pages/index.js +++ b/examples/react/auto-refetching/src/pages/index.tsx @@ -1,14 +1,11 @@ import React from 'react' -import axios from 'axios' - -// import { - useQuery, - useQueryClient, - useMutation, QueryClient, QueryClientProvider, + useMutation, + useQuery, + useQueryClient, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' @@ -29,16 +26,16 @@ function Example() { const { status, data, error, isFetching } = useQuery({ queryKey: ['todos'], - queryFn: async () => { - const res = await axios.get('/api/data') - return res.data + queryFn: async (): Promise> => { + const response = await fetch('/api/data') + return await response.json() }, // Refetch the data every second refetchInterval: intervalMs, }) const addMutation = useMutation({ - mutationFn: (add) => fetch(`/api/data?add=${add}`), + mutationFn: (add: string) => fetch(`/api/data?add=${add}`), onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) @@ -52,7 +49,7 @@ function Example() { return (
-

Auto Refetch with stale-time set to 1s)

+

Auto Refetch with stale-time set to {intervalMs}ms

This example is best experienced on your own machine, where you can open multiple tabs to the same localhost server and see your changes diff --git a/examples/react/auto-refetching/tsconfig.json b/examples/react/auto-refetching/tsconfig.json new file mode 100644 index 0000000000..9575d0eab5 --- /dev/null +++ b/examples/react/auto-refetching/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/examples/react/basic-graphql-request/.eslintrc b/examples/react/basic-graphql-request/.eslintrc deleted file mode 100644 index 4e03b9e10b..0000000000 --- a/examples/react/basic-graphql-request/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["plugin:react/jsx-runtime", "plugin:react-hooks/recommended"] -} diff --git a/examples/react/basic-graphql-request/eslint.config.js b/examples/react/basic-graphql-request/eslint.config.js new file mode 100644 index 0000000000..dee0fcc96c --- /dev/null +++ b/examples/react/basic-graphql-request/eslint.config.js @@ -0,0 +1,19 @@ +import { tanstackConfig } from '@tanstack/config/eslint' +import pluginQuery from '@tanstack/eslint-plugin-query' +import pluginReact from '@eslint-react/eslint-plugin' +import pluginReactHooks from 'eslint-plugin-react-hooks' + +export default [ + ...tanstackConfig, + ...pluginQuery.configs['flat/recommended'], + pluginReact.configs.recommended, + { + plugins: { + 'react-hooks': pluginReactHooks, + }, + rules: { + 'react-hooks/exhaustive-deps': 'error', + 'react-hooks/rules-of-hooks': 'error', + }, + }, +] diff --git a/examples/react/basic-graphql-request/index.html b/examples/react/basic-graphql-request/index.html index 433cf93816..f098940196 100644 --- a/examples/react/basic-graphql-request/index.html +++ b/examples/react/basic-graphql-request/index.html @@ -11,6 +11,6 @@

- + diff --git a/examples/react/basic-graphql-request/package.json b/examples/react/basic-graphql-request/package.json index 14b4602355..c11569a9fe 100644 --- a/examples/react/basic-graphql-request/package.json +++ b/examples/react/basic-graphql-request/package.json @@ -8,27 +8,15 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "graphql": "^16.8.1", - "graphql-request": "^6.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "graphql": "^16.9.0", + "graphql-request": "^7.1.0", + "react": "19.0.0-rc-4c2e457c7c-20240522", + "react-dom": "19.0.0-rc-4c2e457c7c-20240522" }, "devDependencies": { - "@vitejs/plugin-react": "^4.2.1", - "vite": "^5.1.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "@vitejs/plugin-react": "^4.3.1", + "vite": "^5.3.5" } } diff --git a/examples/react/basic-graphql-request/src/index.jsx b/examples/react/basic-graphql-request/src/index.tsx similarity index 84% rename from examples/react/basic-graphql-request/src/index.jsx rename to examples/react/basic-graphql-request/src/index.tsx index b484d73a23..09995939cd 100644 --- a/examples/react/basic-graphql-request/src/index.jsx +++ b/examples/react/basic-graphql-request/src/index.tsx @@ -1,19 +1,24 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' import { - useQuery, - useQueryClient, QueryClient, QueryClientProvider, + useQuery, + useQueryClient, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' -import { request, gql } from 'graphql-request' +import { gql, request } from 'graphql-request' const endpoint = 'https://graphqlzero.almansi.me/api' const queryClient = new QueryClient() +type Post = { + id: number + title: string + body: string +} + function App() { const [postId, setPostId] = React.useState(-1) @@ -45,7 +50,7 @@ function usePosts() { queryFn: async () => { const { posts: { data }, - } = await request( + } = await request<{ posts: { data: Array } }>( endpoint, gql` query { @@ -63,7 +68,11 @@ function usePosts() { }) } -function Posts({ setPostId }) { +function Posts({ + setPostId, +}: { + setPostId: React.Dispatch> +}) { const queryClient = useQueryClient() const { status, data, error, isFetching } = usePosts() @@ -107,11 +116,11 @@ function Posts({ setPostId }) { ) } -function usePost(postId) { - return useQuery( - ['post', postId], - async () => { - const { post } = await request( +function usePost(postId: number) { + return useQuery({ + queryKey: ['post', postId], + queryFn: async () => { + const { post } = await request<{ post: Post }>( endpoint, gql` query { @@ -126,13 +135,17 @@ function usePost(postId) { return post }, - { - enabled: !!postId, - }, - ) + enabled: !!postId, + }) } -function Post({ postId, setPostId }) { +function Post({ + postId, + setPostId, +}: { + postId: number + setPostId: React.Dispatch> +}) { const { status, data, error, isFetching } = usePost(postId) return ( @@ -159,5 +172,5 @@ function Post({ postId, setPostId }) { ) } -const rootElement = document.getElementById('root') +const rootElement = document.getElementById('root') as HTMLElement ReactDOM.createRoot(rootElement).render() diff --git a/examples/react/basic-typescript/tsconfig.json b/examples/react/basic-graphql-request/tsconfig.json similarity index 86% rename from examples/react/basic-typescript/tsconfig.json rename to examples/react/basic-graphql-request/tsconfig.json index 6d545f543f..23a8707ef4 100644 --- a/examples/react/basic-typescript/tsconfig.json +++ b/examples/react/basic-graphql-request/tsconfig.json @@ -7,7 +7,7 @@ "skipLibCheck": true, /* Bundler mode */ - "moduleResolution": "bundler", + "moduleResolution": "Bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, @@ -20,5 +20,5 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"] + "include": ["src", "eslint.config.js"] } diff --git a/examples/react/basic-typescript/.eslintrc b/examples/react/basic-typescript/.eslintrc deleted file mode 100644 index 270fbc9ac0..0000000000 --- a/examples/react/basic-typescript/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": [ - "plugin:react/jsx-runtime", - "plugin:react-hooks/recommended", - "plugin:@tanstack/eslint-plugin-query/recommended" - ] -} diff --git a/examples/react/basic-typescript/README.md b/examples/react/basic-typescript/README.md deleted file mode 100644 index 1cf8892652..0000000000 --- a/examples/react/basic-typescript/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Example - -To run this example: - -- `npm install` -- `npm run dev` diff --git a/examples/react/basic-typescript/index.html b/examples/react/basic-typescript/index.html deleted file mode 100644 index aed742fcef..0000000000 --- a/examples/react/basic-typescript/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - TanStack Query React Basic TypeScript Example App - - - -
- - - diff --git a/examples/react/basic-typescript/package.json b/examples/react/basic-typescript/package.json deleted file mode 100644 index dd89246c5a..0000000000 --- a/examples/react/basic-typescript/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@tanstack/query-example-react-basic-typescript", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "test:types": "tsc" - }, - "dependencies": { - "@tanstack/query-sync-storage-persister": "^5.35.1", - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "@tanstack/react-query-persist-client": "^5.35.1", - "axios": "^1.6.7", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@tanstack/eslint-plugin-query": "^5.32.1", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", - "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.56.0", - "eslint-config-prettier": "^9.1.0", - "typescript": "5.2.2", - "vite": "^5.1.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/examples/react/basic-typescript/public/emblem-light.svg b/examples/react/basic-typescript/public/emblem-light.svg deleted file mode 100644 index a58e69ad5e..0000000000 --- a/examples/react/basic-typescript/public/emblem-light.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - emblem-light - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/examples/react/basic/.eslintrc b/examples/react/basic/.eslintrc deleted file mode 100644 index 270fbc9ac0..0000000000 --- a/examples/react/basic/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": [ - "plugin:react/jsx-runtime", - "plugin:react-hooks/recommended", - "plugin:@tanstack/eslint-plugin-query/recommended" - ] -} diff --git a/examples/react/basic/eslint.config.js b/examples/react/basic/eslint.config.js new file mode 100644 index 0000000000..dee0fcc96c --- /dev/null +++ b/examples/react/basic/eslint.config.js @@ -0,0 +1,19 @@ +import { tanstackConfig } from '@tanstack/config/eslint' +import pluginQuery from '@tanstack/eslint-plugin-query' +import pluginReact from '@eslint-react/eslint-plugin' +import pluginReactHooks from 'eslint-plugin-react-hooks' + +export default [ + ...tanstackConfig, + ...pluginQuery.configs['flat/recommended'], + pluginReact.configs.recommended, + { + plugins: { + 'react-hooks': pluginReactHooks, + }, + rules: { + 'react-hooks/exhaustive-deps': 'error', + 'react-hooks/rules-of-hooks': 'error', + }, + }, +] diff --git a/examples/react/basic/index.html b/examples/react/basic/index.html index acfcd2e4e5..d7c231330c 100644 --- a/examples/react/basic/index.html +++ b/examples/react/basic/index.html @@ -11,6 +11,6 @@
- + diff --git a/examples/react/basic/package.json b/examples/react/basic/package.json index ac1f97e60e..7ea1235066 100644 --- a/examples/react/basic/package.json +++ b/examples/react/basic/package.json @@ -5,30 +5,24 @@ "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "test:types": "tsc" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "axios": "^1.6.7", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@tanstack/query-sync-storage-persister": "^5.51.17", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "@tanstack/react-query-persist-client": "^5.51.17", + "react": "19.0.0-rc-4c2e457c7c-20240522", + "react-dom": "19.0.0-rc-4c2e457c7c-20240522" }, "devDependencies": { - "@tanstack/eslint-plugin-query": "^5.32.1", - "@vitejs/plugin-react": "^4.2.1", - "vite": "^5.1.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "@tanstack/eslint-plugin-query": "^5.51.15", + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^8.57.0", + "typescript": "5.3.3", + "vite": "^5.3.5" } } diff --git a/examples/react/basic/src/index.jsx b/examples/react/basic/src/index.jsx deleted file mode 100644 index e038ea9b33..0000000000 --- a/examples/react/basic/src/index.jsx +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ -import React from 'react' -import ReactDOM from 'react-dom/client' -import axios from 'axios' -import { - useQuery, - useQueryClient, - QueryClient, - QueryClientProvider, -} from '@tanstack/react-query' -import { ReactQueryDevtools } from '@tanstack/react-query-devtools' - -const queryClient = new QueryClient() - -function App() { - const [postId, setPostId] = React.useState(-1) - - return ( - -

- As you visit the posts below, you will notice them in a loading state - the first time you load them. However, after you return to this list and - click on any posts you have already visited again, you will see them - load instantly and background refresh right before your eyes!{' '} - - (You may need to throttle your network speed to simulate longer - loading sequences) - -

- {postId > -1 ? ( - - ) : ( - - )} - -
- ) -} - -function usePosts() { - return useQuery({ - queryKey: ['posts'], - queryFn: async () => { - const { data } = await axios.get( - 'https://jsonplaceholder.typicode.com/posts', - ) - return data - }, - }) -} - -function Posts({ setPostId }) { - const queryClient = useQueryClient() - const { status, data, error, isFetching } = usePosts() - - return ( -
-

Posts

-
- {status === 'pending' ? ( - 'Loading...' - ) : status === 'error' ? ( - Error: {error.message} - ) : ( - <> - -
{isFetching ? 'Background Updating...' : ' '}
- - )} -
-
- ) -} - -const getPostById = async (id) => { - const { data } = await axios.get( - `https://jsonplaceholder.typicode.com/posts/${id}`, - ) - return data -} - -function usePost(postId) { - return useQuery({ - queryKey: ['post', postId], - queryFn: () => getPostById(postId), - enabled: !!postId, - }) -} - -function Post({ postId, setPostId }) { - const { status, data, error, isFetching } = usePost(postId) - - return ( -
- - {!postId || status === 'pending' ? ( - 'Loading...' - ) : status === 'error' ? ( - Error: {error.message} - ) : ( - <> -

{data.title}

-
-

{data.body}

-
-
{isFetching ? 'Background Updating...' : ' '}
- - )} -
- ) -} - -const rootElement = document.getElementById('root') -ReactDOM.createRoot(rootElement).render() diff --git a/examples/react/basic-typescript/src/index.tsx b/examples/react/basic/src/index.tsx similarity index 86% rename from examples/react/basic-typescript/src/index.tsx rename to examples/react/basic/src/index.tsx index 09d700c7c1..052ce4c797 100644 --- a/examples/react/basic-typescript/src/index.tsx +++ b/examples/react/basic/src/index.tsx @@ -1,13 +1,6 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react' import ReactDOM from 'react-dom/client' -import axios from 'axios' -import { - QueryClient, - skipToken, - useQuery, - useQueryClient, -} from '@tanstack/react-query' +import { QueryClient, useQuery, useQueryClient } from '@tanstack/react-query' import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client' import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' @@ -34,10 +27,8 @@ function usePosts() { return useQuery({ queryKey: ['posts'], queryFn: async (): Promise> => { - const { data } = await axios.get( - 'https://jsonplaceholder.typicode.com/posts', - ) - return data + const response = await fetch('https://jsonplaceholder.typicode.com/posts') + return await response.json() }, }) } @@ -56,12 +47,12 @@ function Posts({
{status === 'pending' ? ( 'Loading...' - ) : error instanceof Error ? ( + ) : status === 'error' ? ( Error: {error.message} ) : ( <> {!postId || status === 'pending' ? ( 'Loading...' - ) : error instanceof Error ? ( + ) : status === 'error' ? ( Error: {error.message} ) : ( <> -

{data?.title}

+

{data.title}

-

{data?.body}

+

{data.body}

{isFetching ? 'Background Updating...' : ' '}
diff --git a/examples/react/basic/tsconfig.json b/examples/react/basic/tsconfig.json new file mode 100644 index 0000000000..23a8707ef4 --- /dev/null +++ b/examples/react/basic/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src", "eslint.config.js"] +} diff --git a/examples/react/basic-typescript/vite.config.ts b/examples/react/basic/vite.config.ts similarity index 100% rename from examples/react/basic-typescript/vite.config.ts rename to examples/react/basic/vite.config.ts diff --git a/examples/react/default-query-function/index.html b/examples/react/default-query-function/index.html index 3365e7fa58..07e1d099d2 100644 --- a/examples/react/default-query-function/index.html +++ b/examples/react/default-query-function/index.html @@ -11,6 +11,6 @@
- + diff --git a/examples/react/default-query-function/package.json b/examples/react/default-query-function/package.json index cc583c8bdc..1d6f849a40 100644 --- a/examples/react/default-query-function/package.json +++ b/examples/react/default-query-function/package.json @@ -8,26 +8,14 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "axios": "^1.6.7", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "react": "19.0.0-rc-4c2e457c7c-20240522", + "react-dom": "19.0.0-rc-4c2e457c7c-20240522" }, "devDependencies": { - "@vitejs/plugin-react": "^4.2.1", - "vite": "^5.1.1" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "@vitejs/plugin-react": "^4.3.1", + "typescript": "5.3.3", + "vite": "^5.3.5" } } diff --git a/examples/react/default-query-function/src/index.jsx b/examples/react/default-query-function/src/index.tsx similarity index 81% rename from examples/react/default-query-function/src/index.jsx rename to examples/react/default-query-function/src/index.tsx index 5b494df68e..72a45b7f3c 100644 --- a/examples/react/default-query-function/src/index.jsx +++ b/examples/react/default-query-function/src/index.tsx @@ -1,21 +1,26 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' -import axios from 'axios' import { - useQuery, - useQueryClient, QueryClient, QueryClientProvider, + useQuery, + useQueryClient, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import type { QueryKey } from '@tanstack/react-query' + +type Post = { + id: number + title: string + body: string +} // Define a default query function that will receive the query key -const defaultQueryFn = async ({ queryKey }) => { - const { data } = await axios.get( +const defaultQueryFn = async ({ queryKey }: { queryKey: QueryKey }) => { + const response = await fetch( `https://jsonplaceholder.typicode.com${queryKey[0]}`, ) - return data + return await response.json() } // provide the default query function to your app via the query client @@ -52,11 +57,15 @@ function App() { ) } -function Posts({ setPostId }) { +function Posts({ + setPostId, +}: { + setPostId: React.Dispatch> +}) { const queryClient = useQueryClient() // All you have to do now is pass a key! - const { status, data, error, isFetching } = useQuery({ + const { status, data, error, isFetching } = useQuery>({ queryKey: ['/posts'], }) @@ -79,7 +88,7 @@ function Posts({ setPostId }) { style={ // We can use the queryCache here to show bold links for // ones that are cached - queryClient.getQueryData(['post', post.id]) + queryClient.getQueryData([`/posts/${post.id}`]) ? { fontWeight: 'bold', color: 'green', @@ -100,9 +109,15 @@ function Posts({ setPostId }) { ) } -function Post({ postId, setPostId }) { +function Post({ + postId, + setPostId, +}: { + postId: number + setPostId: React.Dispatch> +}) { // You can even leave out the queryFn and just go straight into options - const { status, data, error, isFetching } = useQuery({ + const { status, data, error, isFetching } = useQuery({ queryKey: [`/posts/${postId}`], enabled: !!postId, }) @@ -131,5 +146,5 @@ function Post({ postId, setPostId }) { ) } -const rootElement = document.getElementById('root') +const rootElement = document.getElementById('root') as HTMLElement ReactDOM.createRoot(rootElement).render() diff --git a/examples/react/default-query-function/tsconfig.json b/examples/react/default-query-function/tsconfig.json new file mode 100644 index 0000000000..23a8707ef4 --- /dev/null +++ b/examples/react/default-query-function/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src", "eslint.config.js"] +} diff --git a/examples/react/default-query-function/vite.config.ts b/examples/react/default-query-function/vite.config.ts new file mode 100644 index 0000000000..9ffcc67574 --- /dev/null +++ b/examples/react/default-query-function/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], +}) diff --git a/examples/react/infinite-query-with-max-pages/next-env.d.ts b/examples/react/infinite-query-with-max-pages/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/react/infinite-query-with-max-pages/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/react/infinite-query-with-max-pages/next.config.js b/examples/react/infinite-query-with-max-pages/next.config.js index 954704d28c..033754658c 100644 --- a/examples/react/infinite-query-with-max-pages/next.config.js +++ b/examples/react/infinite-query-with-max-pages/next.config.js @@ -1,5 +1,13 @@ -module.exports = { +// @ts-check + +/** @type {import('next').NextConfig} */ +const nextConfig = { eslint: { ignoreDuringBuilds: true, }, + typescript: { + ignoreBuildErrors: true, + }, } + +export default nextConfig diff --git a/examples/react/infinite-query-with-max-pages/package.json b/examples/react/infinite-query-with-max-pages/package.json index 2ef51e5523..e32e91c1aa 100644 --- a/examples/react/infinite-query-with-max-pages/package.json +++ b/examples/react/infinite-query-with-max-pages/package.json @@ -1,19 +1,22 @@ { "name": "@tanstack/query-example-react-infinite-query-with-max-pages", "private": true, + "type": "module", "scripts": { "dev": "next", "build": "next build", "start": "next start" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "axios": "^1.6.7", - "isomorphic-unfetch": "4.0.2", - "next": "^14.0.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "next": "^14.2.5", "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-intersection-observer": "^8.34.0" + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "typescript": "5.3.3" } } diff --git a/examples/react/infinite-query-with-max-pages/src/pages/api/projects.js b/examples/react/infinite-query-with-max-pages/src/pages/api/projects.ts similarity index 78% rename from examples/react/infinite-query-with-max-pages/src/pages/api/projects.js rename to examples/react/infinite-query-with-max-pages/src/pages/api/projects.ts index a13fbee1aa..29b5228484 100644 --- a/examples/react/infinite-query-with-max-pages/src/pages/api/projects.js +++ b/examples/react/infinite-query-with-max-pages/src/pages/api/projects.ts @@ -1,5 +1,6 @@ -// an endpoint for getting projects data -export default (req, res) => { +import type { NextApiRequest, NextApiResponse } from 'next' + +export default (req: NextApiRequest, res: NextApiResponse) => { const cursor = parseInt(req.query.cursor) || 0 const pageSize = 4 diff --git a/examples/react/infinite-query-with-max-pages/src/pages/index.js b/examples/react/infinite-query-with-max-pages/src/pages/index.tsx similarity index 95% rename from examples/react/infinite-query-with-max-pages/src/pages/index.js rename to examples/react/infinite-query-with-max-pages/src/pages/index.tsx index ad7e6b6858..29fac3d44a 100644 --- a/examples/react/infinite-query-with-max-pages/src/pages/index.js +++ b/examples/react/infinite-query-with-max-pages/src/pages/index.tsx @@ -1,9 +1,8 @@ import React from 'react' -import axios from 'axios' import { - useInfiniteQuery, QueryClient, QueryClientProvider, + useInfiniteQuery, } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' @@ -32,8 +31,8 @@ function Example() { } = useInfiniteQuery({ queryKey: ['projects'], queryFn: async ({ pageParam }) => { - const res = await axios.get('/api/projects?cursor=' + pageParam) - return res.data + const response = await fetch(`/api/projects?cursor=${pageParam}`) + return await response.json() }, initialPageParam: 0, getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined, diff --git a/examples/react/infinite-query-with-max-pages/tsconfig.json b/examples/react/infinite-query-with-max-pages/tsconfig.json new file mode 100644 index 0000000000..9575d0eab5 --- /dev/null +++ b/examples/react/infinite-query-with-max-pages/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/examples/react/load-more-infinite-scroll/next-env.d.ts b/examples/react/load-more-infinite-scroll/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/react/load-more-infinite-scroll/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/react/load-more-infinite-scroll/next.config.js b/examples/react/load-more-infinite-scroll/next.config.js index 954704d28c..033754658c 100644 --- a/examples/react/load-more-infinite-scroll/next.config.js +++ b/examples/react/load-more-infinite-scroll/next.config.js @@ -1,5 +1,13 @@ -module.exports = { +// @ts-check + +/** @type {import('next').NextConfig} */ +const nextConfig = { eslint: { ignoreDuringBuilds: true, }, + typescript: { + ignoreBuildErrors: true, + }, } + +export default nextConfig diff --git a/examples/react/load-more-infinite-scroll/package.json b/examples/react/load-more-infinite-scroll/package.json index 03843406f3..40bc5b27f6 100644 --- a/examples/react/load-more-infinite-scroll/package.json +++ b/examples/react/load-more-infinite-scroll/package.json @@ -1,19 +1,23 @@ { "name": "@tanstack/query-example-react-load-more-infinite-scroll", "private": true, + "type": "module", "scripts": { "dev": "next", "build": "next build", "start": "next start" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "axios": "^1.6.7", - "isomorphic-unfetch": "4.0.2", - "next": "^14.0.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "next": "^14.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-intersection-observer": "^8.34.0" + "react-intersection-observer": "^9.13.0" + }, + "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "typescript": "5.3.3" } } diff --git a/examples/react/load-more-infinite-scroll/src/pages/about.js b/examples/react/load-more-infinite-scroll/src/pages/about.tsx similarity index 100% rename from examples/react/load-more-infinite-scroll/src/pages/about.js rename to examples/react/load-more-infinite-scroll/src/pages/about.tsx diff --git a/examples/react/load-more-infinite-scroll/src/pages/api/projects.js b/examples/react/load-more-infinite-scroll/src/pages/api/projects.ts similarity index 78% rename from examples/react/load-more-infinite-scroll/src/pages/api/projects.js rename to examples/react/load-more-infinite-scroll/src/pages/api/projects.ts index 03492c0a15..493a453a96 100644 --- a/examples/react/load-more-infinite-scroll/src/pages/api/projects.js +++ b/examples/react/load-more-infinite-scroll/src/pages/api/projects.ts @@ -1,5 +1,6 @@ -// an endpoint for getting projects data -export default (req, res) => { +import type { NextApiRequest, NextApiResponse } from 'next' + +export default (req: NextApiRequest, res: NextApiResponse) => { const cursor = parseInt(req.query.cursor) || 0 const pageSize = 5 diff --git a/examples/react/load-more-infinite-scroll/src/pages/index.js b/examples/react/load-more-infinite-scroll/src/pages/index.tsx similarity index 87% rename from examples/react/load-more-infinite-scroll/src/pages/index.js rename to examples/react/load-more-infinite-scroll/src/pages/index.tsx index 1635230ca5..9aa6742d15 100644 --- a/examples/react/load-more-infinite-scroll/src/pages/index.js +++ b/examples/react/load-more-infinite-scroll/src/pages/index.tsx @@ -1,6 +1,5 @@ import React from 'react' import Link from 'next/link' -import axios from 'axios' import { useInView } from 'react-intersection-observer' import { useInfiniteQuery, @@ -35,13 +34,19 @@ function Example() { hasPreviousPage, } = useInfiniteQuery({ queryKey: ['projects'], - queryFn: async ({ pageParam }) => { - const res = await axios.get('/api/projects?cursor=' + pageParam) - return res.data + queryFn: async ({ + pageParam, + }): Promise<{ + data: Array<{ name: string; id: number }> + previousId: number + nextId: number + }> => { + const response = await fetch(`/api/projects?cursor=${pageParam}`) + return await response.json() }, initialPageParam: 0, - getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined, - getNextPageParam: (lastPage) => lastPage.nextId ?? undefined, + getPreviousPageParam: (firstPage) => firstPage.previousId, + getNextPageParam: (lastPage) => lastPage.nextId, }) React.useEffect(() => { diff --git a/examples/react/load-more-infinite-scroll/tsconfig.json b/examples/react/load-more-infinite-scroll/tsconfig.json new file mode 100644 index 0000000000..9575d0eab5 --- /dev/null +++ b/examples/react/load-more-infinite-scroll/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/examples/react/nextjs-app-prefetching/.eslintrc.cjs b/examples/react/nextjs-app-prefetching/.eslintrc.cjs new file mode 100644 index 0000000000..cb40aee1b4 --- /dev/null +++ b/examples/react/nextjs-app-prefetching/.eslintrc.cjs @@ -0,0 +1,9 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ['plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'], + settings: { + react: { + version: 'detect', + }, + }, +} diff --git a/examples/react/basic-typescript/.gitignore b/examples/react/nextjs-app-prefetching/.gitignore similarity index 64% rename from examples/react/basic-typescript/.gitignore rename to examples/react/nextjs-app-prefetching/.gitignore index 4673b022e5..8f322f0d8f 100644 --- a/examples/react/basic-typescript/.gitignore +++ b/examples/react/nextjs-app-prefetching/.gitignore @@ -8,20 +8,28 @@ # testing /coverage +# next.js +/.next/ +/out/ + # production /build -pnpm-lock.yaml -yarn.lock -package-lock.json - # misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +*.pem +# debug npm-debug.log* yarn-debug.log* yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/examples/react/nextjs-app-prefetching/README.md b/examples/react/nextjs-app-prefetching/README.md new file mode 100644 index 0000000000..f4da3c4c1c --- /dev/null +++ b/examples/react/nextjs-app-prefetching/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/react/nextjs-app-prefetching/app/favicon.ico b/examples/react/nextjs-app-prefetching/app/favicon.ico new file mode 100644 index 0000000000..718d6fea48 Binary files /dev/null and b/examples/react/nextjs-app-prefetching/app/favicon.ico differ diff --git a/examples/react/nextjs-app-prefetching/app/get-query-client.ts b/examples/react/nextjs-app-prefetching/app/get-query-client.ts new file mode 100644 index 0000000000..9ca1cc407e --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/get-query-client.ts @@ -0,0 +1,37 @@ +import { + QueryClient, + defaultShouldDehydrateQuery, + isServer, +} from '@tanstack/react-query' + +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, + }, + dehydrate: { + // include pending queries in dehydration + shouldDehydrateQuery: (query) => + defaultShouldDehydrateQuery(query) || + query.state.status === 'pending', + }, + }, + }) +} + +let browserQueryClient: QueryClient | undefined = undefined + +export function getQueryClient() { + if (isServer) { + // Server: always make a new query client + return makeQueryClient() + } else { + // Browser: make a new query client if we don't already have one + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient() + return browserQueryClient + } +} diff --git a/examples/react/nextjs-app-prefetching/app/layout.tsx b/examples/react/nextjs-app-prefetching/app/layout.tsx new file mode 100644 index 0000000000..eec241445e --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/layout.tsx @@ -0,0 +1,22 @@ +import Providers from './providers' +import type React from 'react' +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Create Next App', + description: 'Generated by create next app', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {children} + + + ) +} diff --git a/examples/react/nextjs-app-prefetching/app/page.tsx b/examples/react/nextjs-app-prefetching/app/page.tsx new file mode 100644 index 0000000000..fc1113beac --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/page.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { HydrationBoundary, dehydrate } from '@tanstack/react-query' +import { pokemonOptions } from '@/app/pokemon' +import { getQueryClient } from '@/app/get-query-client' +import { PokemonInfo } from './pokemon-info' + +export default function Home() { + const queryClient = getQueryClient() + + void queryClient.prefetchQuery(pokemonOptions) + + return ( +
+

Pokemon Info

+ + + +
+ ) +} diff --git a/examples/react/nextjs-app-prefetching/app/pokemon-info.tsx b/examples/react/nextjs-app-prefetching/app/pokemon-info.tsx new file mode 100644 index 0000000000..6490f6f339 --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/pokemon-info.tsx @@ -0,0 +1,18 @@ +'use client' + +import React from 'react' +import { useSuspenseQuery } from '@tanstack/react-query' +import { pokemonOptions } from '@/app/pokemon' + +export function PokemonInfo() { + const { data } = useSuspenseQuery(pokemonOptions) + + return ( +
+
+ {data.name} +

I'm {data.name}

+
+
+ ) +} diff --git a/examples/react/nextjs-app-prefetching/app/pokemon.ts b/examples/react/nextjs-app-prefetching/app/pokemon.ts new file mode 100644 index 0000000000..6e4c780ea8 --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/pokemon.ts @@ -0,0 +1,10 @@ +import { queryOptions } from '@tanstack/react-query' + +export const pokemonOptions = queryOptions({ + queryKey: ['pokemon'], + queryFn: async () => { + const response = await fetch('https://pokeapi.co/api/v2/pokemon/25') + + return response.json() + }, +}) diff --git a/examples/react/nextjs-app-prefetching/app/providers.tsx b/examples/react/nextjs-app-prefetching/app/providers.tsx new file mode 100644 index 0000000000..f5098b4d0a --- /dev/null +++ b/examples/react/nextjs-app-prefetching/app/providers.tsx @@ -0,0 +1,16 @@ +'use client' +import { QueryClientProvider } from '@tanstack/react-query' +import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import { getQueryClient } from '@/app/get-query-client' +import type * as React from 'react' + +export default function Providers({ children }: { children: React.ReactNode }) { + const queryClient = getQueryClient() + + return ( + + {children} + + + ) +} diff --git a/examples/react/nextjs-app-prefetching/next.config.js b/examples/react/nextjs-app-prefetching/next.config.js new file mode 100644 index 0000000000..033754658c --- /dev/null +++ b/examples/react/nextjs-app-prefetching/next.config.js @@ -0,0 +1,13 @@ +// @ts-check + +/** @type {import('next').NextConfig} */ +const nextConfig = { + eslint: { + ignoreDuringBuilds: true, + }, + typescript: { + ignoreBuildErrors: true, + }, +} + +export default nextConfig diff --git a/examples/react/nextjs-app-prefetching/package.json b/examples/react/nextjs-app-prefetching/package.json new file mode 100644 index 0000000000..71ec3b9bdd --- /dev/null +++ b/examples/react/nextjs-app-prefetching/package.json @@ -0,0 +1,23 @@ +{ + "name": "@tanstack/query-example-react-nextjs-app-prefetching", + "private": true, + "type": "module", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "test:types": "tsc" + }, + "dependencies": { + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "next": "^15.0.0-rc.0", + "react": "19.0.0-rc-4c2e457c7c-20240522", + "react-dom": "19.0.0-rc-4c2e457c7c-20240522" + }, + "devDependencies": { + "@types/react": "npm:types-react@rc", + "@types/react-dom": "npm:types-react-dom@rc", + "typescript": "5.3.3" + } +} diff --git a/examples/react/nextjs-app-prefetching/tsconfig.json b/examples/react/nextjs-app-prefetching/tsconfig.json new file mode 100644 index 0000000000..44eb6012cc --- /dev/null +++ b/examples/react/nextjs-app-prefetching/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".eslintrc.cjs" + ], + "exclude": ["node_modules"] +} diff --git a/examples/react/nextjs-suspense-streaming/next.config.js b/examples/react/nextjs-suspense-streaming/next.config.js index 8d249b795b..591cd313c3 100644 --- a/examples/react/nextjs-suspense-streaming/next.config.js +++ b/examples/react/nextjs-suspense-streaming/next.config.js @@ -1,8 +1,13 @@ +// @ts-check + /** @type {import('next').NextConfig} */ const nextConfig = { eslint: { ignoreDuringBuilds: true, }, + typescript: { + ignoreBuildErrors: true, + }, webpack: (config) => { if (config.name === 'server') config.optimization.concatenateModules = false @@ -10,4 +15,4 @@ const nextConfig = { }, } -module.exports = nextConfig +export default nextConfig diff --git a/examples/react/nextjs-suspense-streaming/package.json b/examples/react/nextjs-suspense-streaming/package.json index aea0be4681..412a8e4afc 100644 --- a/examples/react/nextjs-suspense-streaming/package.json +++ b/examples/react/nextjs-suspense-streaming/package.json @@ -1,6 +1,7 @@ { "name": "@tanstack/query-example-nextjs-suspense-streaming", "private": true, + "type": "module", "scripts": { "dev": "next dev", "build": "next build", @@ -8,17 +9,15 @@ "test:types": "tsc" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "@tanstack/react-query-next-experimental": "^5.35.1", - "next": "^14.0.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "@tanstack/react-query-next-experimental": "^5.51.17", + "next": "^14.2.5", "react": "^18.2.0", - "react-dom": "^18.2.0", - "superjson": "^1.13.3" + "react-dom": "^18.2.0" }, "devDependencies": { - "@types/node": "^18.19.3", - "@types/react": "^18.2.55", - "typescript": "5.2.2" + "@types/react": "^18.2.79", + "typescript": "5.3.3" } } diff --git a/examples/react/nextjs-suspense-streaming/src/app/page.tsx b/examples/react/nextjs-suspense-streaming/src/app/page.tsx index 50fa21bfae..4c17668cbc 100644 --- a/examples/react/nextjs-suspense-streaming/src/app/page.tsx +++ b/examples/react/nextjs-suspense-streaming/src/app/page.tsx @@ -1,11 +1,11 @@ 'use client' -import { useSuspenseQuery } from '@tanstack/react-query' +import { isServer, useSuspenseQuery } from '@tanstack/react-query' import { Suspense } from 'react' export const runtime = 'edge' // 'nodejs' (default) | 'edge' function getBaseURL() { - if (typeof window !== 'undefined') { + if (!isServer) { return '' } if (process.env.VERCEL_URL) { diff --git a/examples/react/nextjs-suspense-streaming/src/app/providers.tsx b/examples/react/nextjs-suspense-streaming/src/app/providers.tsx index 840ccde40d..b4990842e5 100644 --- a/examples/react/nextjs-suspense-streaming/src/app/providers.tsx +++ b/examples/react/nextjs-suspense-streaming/src/app/providers.tsx @@ -1,22 +1,37 @@ -// app/providers.jsx 'use client' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + QueryClient, + QueryClientProvider, + isServer, +} from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import * as React from 'react' import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental' +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, + }, + }, + }) +} + +let browserQueryClient: QueryClient | undefined = undefined + +function getQueryClient() { + if (isServer) { + return makeQueryClient() + } else { + if (!browserQueryClient) browserQueryClient = makeQueryClient() + return browserQueryClient + } +} + export function Providers(props: { children: React.ReactNode }) { - const [queryClient] = React.useState( - () => - new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 1000, - }, - }, - }), - ) + const queryClient = getQueryClient() return ( diff --git a/examples/react/nextjs/next-env.d.ts b/examples/react/nextjs/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/react/nextjs/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/react/nextjs/next.config.js b/examples/react/nextjs/next.config.js index 954704d28c..033754658c 100644 --- a/examples/react/nextjs/next.config.js +++ b/examples/react/nextjs/next.config.js @@ -1,5 +1,13 @@ -module.exports = { +// @ts-check + +/** @type {import('next').NextConfig} */ +const nextConfig = { eslint: { ignoreDuringBuilds: true, }, + typescript: { + ignoreBuildErrors: true, + }, } + +export default nextConfig diff --git a/examples/react/nextjs/package.json b/examples/react/nextjs/package.json index 3934992e33..b61672204a 100644 --- a/examples/react/nextjs/package.json +++ b/examples/react/nextjs/package.json @@ -1,19 +1,22 @@ { "name": "@tanstack/query-example-react-nextjs", "private": true, + "type": "module", "scripts": { "dev": "next", "build": "next build", "start": "next start" }, "dependencies": { - "@tanstack/react-query": "^5.35.1", - "@tanstack/react-query-devtools": "^5.35.1", - "ky": "^1.2.0", - "next": "^14.0.0", + "@tanstack/react-query": "^5.51.17", + "@tanstack/react-query-devtools": "^5.51.17", + "next": "^14.2.5", "react": "^18.2.0", - "react-dom": "^18.2.0", - "resolve-from": "^5.0.0", - "web-streams-polyfill": "^3.3.2" + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "typescript": "5.3.3" } } diff --git a/examples/react/nextjs/src/components/Header/index.js b/examples/react/nextjs/src/components/Header.tsx similarity index 100% rename from examples/react/nextjs/src/components/Header/index.js rename to examples/react/nextjs/src/components/Header.tsx diff --git a/examples/react/nextjs/src/components/InfoBox/index.js b/examples/react/nextjs/src/components/InfoBox.tsx similarity index 83% rename from examples/react/nextjs/src/components/InfoBox/index.js rename to examples/react/nextjs/src/components/InfoBox.tsx index b0ff42f7d3..4bc1ecbbea 100644 --- a/examples/react/nextjs/src/components/InfoBox/index.js +++ b/examples/react/nextjs/src/components/InfoBox.tsx @@ -1,6 +1,6 @@ import React from 'react' -const InfoBox = ({ children }) => ( +const InfoBox = ({ children }: { children: React.ReactNode }) => (