diff --git a/CHANGELOG.md b/CHANGELOG.md index 1431d870245..6f55711b672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 5.10.0 + +- Upgraded `@tanstack/react-query` to `5.83.0`. You might have duplicate versions if you already had it in your dependencies. Should you have an error mentioning the `QueryContext`, make sure you only have one version in your package manager lock file. + ## 5.9.1 * Fix `` empty throws error when used in standalone mode ([#10812](https://github.com/marmelab/react-admin/pull/10812)) ([fzaninotto](https://github.com/fzaninotto)) diff --git a/docs/List.md b/docs/List.md index d680c9df6db..e5968477913 100644 --- a/docs/List.md +++ b/docs/List.md @@ -1174,6 +1174,42 @@ const ProductList = () => ( ) ``` +## Enabling Data Fetching Conditionally + +You might want to allow data to be fetched only when at least some filters have been set. You can leverage TanStack react-query `enabled` option for that. It accepts a function that receives the query as its only parameter. As react-admin always format the `queryKey` as `[ResourceName, DataProviderMethod, DataProviderParams]`, you can check that there is at least a filter in this function: + +{% raw %} +```tsx +export const PostList = () => ( + { + const listParams = query.queryKey[2] as GetListParams; + return listParams.filter.q?.length > 2; + } + }} + > + + context.filterValues.q?.length > 2 ? ( + + Type a search term to fetch data + + ) : ( + + {/* your fields */} + + ) + } + /> + +) +``` +{% endraw %} + +**Note**: Notice we display some custom UI when there is no filter. This is because otherwise, users would see the loading UI as Tanstack Query will set the `isPending` property of the underlying query to `true` if the query isn't enabled. + ## Accessing Extra Response Data If `dataProvider.getList()` returns additional metadata in the response under the `meta` key, you can access it in the list view using the `meta` property of the `ListContext`. diff --git a/examples/simple/package.json b/examples/simple/package.json index 6e95cf8970d..54a6466436f 100644 --- a/examples/simple/package.json +++ b/examples/simple/package.json @@ -12,8 +12,8 @@ "dependencies": { "@mui/icons-material": "^5.16.12", "@mui/material": "^5.16.12", - "@tanstack/react-query": "^5.21.7", - "@tanstack/react-query-devtools": "^5.21.7", + "@tanstack/react-query": "^5.83.0", + "@tanstack/react-query-devtools": "^5.83.0", "jsonexport": "^3.2.0", "lodash": "~4.17.5", "ra-data-fakerest": "^5.9.1", diff --git a/packages/ra-core/package.json b/packages/ra-core/package.json index 2d9c50f8031..1c77b0283b8 100644 --- a/packages/ra-core/package.json +++ b/packages/ra-core/package.json @@ -57,8 +57,7 @@ "react-router-dom": "^6.28.1 || ^7.1.1" }, "dependencies": { - "@tanstack/react-query": "^5.21.7", - "clsx": "^2.1.1", + "@tanstack/react-query": "^5.83.0", "date-fns": "^3.6.0", "eventemitter3": "^5.0.1", "inflection": "^3.0.0", diff --git a/packages/ra-core/src/auth/useAuthState.ts b/packages/ra-core/src/auth/useAuthState.ts index aa75ef8d5cd..868da334f94 100644 --- a/packages/ra-core/src/auth/useAuthState.ts +++ b/packages/ra-core/src/auth/useAuthState.ts @@ -150,7 +150,7 @@ const useAuthState = ( return authProvider != null ? result - : (noAuthProviderQueryResult as UseAuthStateResult); + : (noAuthProviderQueryResult as unknown as UseAuthStateResult); }; type UseAuthStateOptions = Omit< diff --git a/packages/ra-core/src/auth/useCanAccess.ts b/packages/ra-core/src/auth/useCanAccess.ts index 63db7906666..ead40b597dc 100644 --- a/packages/ra-core/src/auth/useCanAccess.ts +++ b/packages/ra-core/src/auth/useCanAccess.ts @@ -93,7 +93,7 @@ export const useCanAccess = < return authProviderHasCanAccess ? result - : (emptyQueryObserverResult as UseCanAccessResult); + : (emptyQueryObserverResult as unknown as UseCanAccessResult); }; const emptyQueryObserverResult = { diff --git a/packages/ra-core/src/auth/usePermissions.ts b/packages/ra-core/src/auth/usePermissions.ts index eddf21142c1..9ef83079a08 100644 --- a/packages/ra-core/src/auth/usePermissions.ts +++ b/packages/ra-core/src/auth/usePermissions.ts @@ -108,7 +108,10 @@ const usePermissions = ( ); return !authProvider || !authProvider.getPermissions - ? (fakeQueryResult as UsePermissionsResult) + ? (fakeQueryResult as unknown as UsePermissionsResult< + PermissionsType, + ErrorType + >) : result; }; diff --git a/packages/ra-core/src/controller/input/useReferenceInputController.ts b/packages/ra-core/src/controller/input/useReferenceInputController.ts index 7ddbced53d2..c10f2f7ebd4 100644 --- a/packages/ra-core/src/controller/input/useReferenceInputController.ts +++ b/packages/ra-core/src/controller/input/useReferenceInputController.ts @@ -116,8 +116,8 @@ export const useReferenceInputController = ( } = useReference({ id: currentValue, reference, - // @ts-ignore the types of the queryOptions for the getMAny and getList are not compatible options: { + // @ts-ignore the types of the queryOptions for the getMAny and getList are not compatible enabled: currentValue != null && currentValue !== '', meta, ...otherQueryOptions, diff --git a/packages/ra-core/src/dataProvider/useGetList.ts b/packages/ra-core/src/dataProvider/useGetList.ts index aa24430d175..e16296dfb3a 100644 --- a/packages/ra-core/src/dataProvider/useGetList.ts +++ b/packages/ra-core/src/dataProvider/useGetList.ts @@ -176,7 +176,7 @@ export const useGetList = < } : result, [result] - ) as UseQueryResult & { + ) as unknown as UseQueryResult & { total?: number; pageInfo?: { hasNextPage?: boolean; diff --git a/packages/ra-core/src/dataProvider/useGetManyReference.ts b/packages/ra-core/src/dataProvider/useGetManyReference.ts index 001e930fc6b..c6639a9147d 100644 --- a/packages/ra-core/src/dataProvider/useGetManyReference.ts +++ b/packages/ra-core/src/dataProvider/useGetManyReference.ts @@ -155,7 +155,7 @@ export const useGetManyReference = < } : result, [result] - ) as UseQueryResult & { + ) as unknown as UseQueryResult & { total?: number; pageInfo?: { hasNextPage?: boolean; diff --git a/packages/ra-core/src/dataProvider/useInfiniteGetList.ts b/packages/ra-core/src/dataProvider/useInfiniteGetList.ts index 76a13914540..34c85411532 100644 --- a/packages/ra-core/src/dataProvider/useInfiniteGetList.ts +++ b/packages/ra-core/src/dataProvider/useInfiniteGetList.ts @@ -248,7 +248,6 @@ export type UseInfiniteGetListOptions< GetInfiniteListResult, ErrorType, InfiniteData>, - GetInfiniteListResult, QueryKey, number >, diff --git a/packages/ra-no-code/package.json b/packages/ra-no-code/package.json index fb9640764d7..062676639fb 100644 --- a/packages/ra-no-code/package.json +++ b/packages/ra-no-code/package.json @@ -42,7 +42,7 @@ "react-dom": "^18.0.0 || ^19.0.0" }, "dependencies": { - "@tanstack/react-query": "^5.21.7", + "@tanstack/react-query": "^5.83.0", "clsx": "^2.1.1", "date-fns": "^3.6.0", "inflection": "^3.0.0", diff --git a/packages/ra-ui-materialui/package.json b/packages/ra-ui-materialui/package.json index f4f3acf138a..99ea6ceba69 100644 --- a/packages/ra-ui-materialui/package.json +++ b/packages/ra-ui-materialui/package.json @@ -68,7 +68,7 @@ "react-router-dom": "^6.28.1 || ^7.1.1" }, "dependencies": { - "@tanstack/react-query": "^5.21.7", + "@tanstack/react-query": "^5.83.0", "autosuggest-highlight": "^3.1.1", "clsx": "^2.1.1", "css-mediaquery": "^0.1.2", diff --git a/packages/ra-ui-materialui/src/list/List.stories.tsx b/packages/ra-ui-materialui/src/list/List.stories.tsx index 9650ef9bf08..6858879fd97 100644 --- a/packages/ra-ui-materialui/src/list/List.stories.tsx +++ b/packages/ra-ui-materialui/src/list/List.stories.tsx @@ -1,11 +1,13 @@ import * as React from 'react'; -import { Admin, AutocompleteInput } from 'react-admin'; +import { Admin, AutocompleteInput, CardContentInner } from 'react-admin'; import { CustomRoutes, Resource, useListContext, TestMemoryRouter, DataProvider, + GetListParams, + WithListContext, } from 'ra-core'; import fakeRestDataProvider from 'ra-data-fakerest'; import { @@ -142,7 +144,10 @@ const data = { authors: [], }; -const defaultDataProvider = fakeRestDataProvider(data); +const defaultDataProvider = fakeRestDataProvider( + data, + process.env.NODE_ENV !== 'test' +); const BookList = () => { const { error, isPending } = useListContext(); @@ -229,6 +234,45 @@ export const Filters = () => ( ); +export const ConditionalDataFetching = () => ( + + + ( + ]} + empty={false} + queryOptions={{ + enabled: query => { + const params = query + .queryKey[2] as GetListParams; + return ( + params.filter.q != null && + params.filter.q !== '' + ); + }, + }} + > + + context.filterValues.q == null || + context.filterValues.q === '' ? ( + + Type a search term to fetch data + + ) : ( + + ) + } + /> + + )} + /> + + +); + export const Filter = () => ( diff --git a/packages/react-admin/package.json b/packages/react-admin/package.json index 8daf18470a2..5a6cc19b341 100644 --- a/packages/react-admin/package.json +++ b/packages/react-admin/package.json @@ -41,6 +41,7 @@ "@emotion/styled": "^11.14.0", "@mui/icons-material": "^5.16.12 || ^6.0.0 || ^7.0.0", "@mui/material": "^5.16.12 || ^6.0.0 || ^7.0.0", + "@tanstack/react-query": "^5.83.0", "ra-core": "^5.9.1", "ra-i18n-polyglot": "^5.9.1", "ra-language-english": "^5.9.1", diff --git a/yarn.lock b/yarn.lock index f768b9d12f3..b4c49d9c823 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4312,40 +4312,40 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:5.47.0": - version: 5.47.0 - resolution: "@tanstack/query-core@npm:5.47.0" - checksum: 2d2378dbde2b0610b6356fcdb56904aa9d41c140c17ceb55e257b918c8555484ff36743a6a37768575631be96b9291eedc53723cd80326783095499cb97db049 +"@tanstack/query-core@npm:5.83.0": + version: 5.83.0 + resolution: "@tanstack/query-core@npm:5.83.0" + checksum: e6dc480bc99eaca552a9ad65423788b60368cf99308681252fc7dbe42a3f2c1c978db0d3471cc3349b9112cfb4d967ace4e192a1d7e987e30c5c1ff74809c77c languageName: node linkType: hard -"@tanstack/query-devtools@npm:5.47.0": - version: 5.47.0 - resolution: "@tanstack/query-devtools@npm:5.47.0" - checksum: b6223395794d08f96d57395c0dcdfbc7cc73c311e82f1a7a13b8685ad8f0e4f10b537df46f7e7e4b65bc29f480a915f246937310d650e01d7db915f4c4757ada +"@tanstack/query-devtools@npm:5.81.2": + version: 5.81.2 + resolution: "@tanstack/query-devtools@npm:5.81.2" + checksum: f942cba7bd3ecb471063cd472eeebb2ec76005feeb7e0f357b191da5ab9f769aa767bc88d4da82b2b39c4fcbb16dfed38ce3c77b6eea4d4c30405368c1120207 languageName: node linkType: hard -"@tanstack/react-query-devtools@npm:^5.21.7": - version: 5.47.0 - resolution: "@tanstack/react-query-devtools@npm:5.47.0" +"@tanstack/react-query-devtools@npm:^5.83.0": + version: 5.83.0 + resolution: "@tanstack/react-query-devtools@npm:5.83.0" dependencies: - "@tanstack/query-devtools": "npm:5.47.0" + "@tanstack/query-devtools": "npm:5.81.2" peerDependencies: - "@tanstack/react-query": ^5.47.0 + "@tanstack/react-query": ^5.83.0 react: ^18 || ^19 - checksum: 1c2a5916b8ac3c580263114c6ff5bf780f655d777ddd1027187f200f6a29703e28be98fadd0918537eb3f07cbfe283013f4212eafa7facde25116ab42b38d4e9 + checksum: 9d3c0c4ba5d5f42d1e76a5d009d768fe407e2bcdfa24986236a5b501bf41de8a04c30ebca97c871f822f6c20e508490943dbe0602640770d95f518cce9e7a760 languageName: node linkType: hard -"@tanstack/react-query@npm:^5.21.7": - version: 5.47.0 - resolution: "@tanstack/react-query@npm:5.47.0" +"@tanstack/react-query@npm:^5.83.0": + version: 5.83.0 + resolution: "@tanstack/react-query@npm:5.83.0" dependencies: - "@tanstack/query-core": "npm:5.47.0" + "@tanstack/query-core": "npm:5.83.0" peerDependencies: - react: ^18.0.0 - checksum: ed94c3255fd20180b0d133138f621ab471729c218c926321d316c3565061c7127e6f1f60c5020ef40455c740b8b5a525bd91292a271f63e7315114c810ddff6f + react: ^18 || ^19 + checksum: 883229f9219ca906a54d7caafd44d59b57db5dbe87e954f8a7027f460e9f8b97842dfbd0d676dc3111d577baf312c64f6c1fdd67cd1e4b0f0bf574e29670c606 languageName: node linkType: hard @@ -16027,14 +16027,13 @@ __metadata: resolution: "ra-core@workspace:packages/ra-core" dependencies: "@hookform/resolvers": "npm:^3.2.0" - "@tanstack/react-query": "npm:^5.21.7" + "@tanstack/react-query": "npm:^5.83.0" "@testing-library/react": "npm:^15.0.7" "@types/jest": "npm:^29.5.2" "@types/jscodeshift": "npm:^0.11.11" "@types/node": "npm:^20.10.7" "@types/node-polyglot": "npm:^0.4.31" "@types/react": "npm:^18.3.3" - clsx: "npm:^2.1.1" cross-env: "npm:^5.2.0" date-fns: "npm:^3.6.0" echarts: "npm:^5.6.0" @@ -16271,7 +16270,7 @@ __metadata: version: 0.0.0-use.local resolution: "ra-no-code@workspace:packages/ra-no-code" dependencies: - "@tanstack/react-query": "npm:^5.21.7" + "@tanstack/react-query": "npm:^5.83.0" "@testing-library/react": "npm:^15.0.7" "@testing-library/user-event": "npm:^14.5.2" clsx: "npm:^2.1.1" @@ -16305,7 +16304,7 @@ __metadata: "@mui/material": "npm:^5.16.12" "@mui/system": "npm:^5.16.12" "@mui/utils": "npm:^5.16.12" - "@tanstack/react-query": "npm:^5.21.7" + "@tanstack/react-query": "npm:^5.83.0" "@testing-library/react": "npm:^15.0.7" "@types/dompurify": "npm:^3.0.2" "@types/react": "npm:^18.3.3" @@ -16515,6 +16514,7 @@ __metadata: "@emotion/styled": "npm:^11.14.0" "@mui/icons-material": "npm:^5.16.12 || ^6.0.0 || ^7.0.0" "@mui/material": "npm:^5.16.12 || ^6.0.0 || ^7.0.0" + "@tanstack/react-query": "npm:^5.83.0" cross-env: "npm:^5.2.0" expect: "npm:^27.4.6" ra-core: "npm:^5.9.1" @@ -17860,8 +17860,8 @@ __metadata: "@hookform/devtools": "npm:^4.3.3" "@mui/icons-material": "npm:^5.16.12" "@mui/material": "npm:^5.16.12" - "@tanstack/react-query": "npm:^5.21.7" - "@tanstack/react-query-devtools": "npm:^5.21.7" + "@tanstack/react-query": "npm:^5.83.0" + "@tanstack/react-query-devtools": "npm:^5.83.0" "@vitejs/plugin-react": "npm:^4.3.4" jsonexport: "npm:^3.2.0" little-state-machine: "npm:^4.8.1"