diff --git a/package-lock.json b/package-lock.json
index 59c1eec68..2cc1cc03e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,7 +41,7 @@
"@openedx/paragon": "^23.5.0",
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "1.9.7",
- "@tanstack/react-query": "4.40.1",
+ "@tanstack/react-query": "5.89.0",
"@tinymce/tinymce-react": "^3.14.0",
"classnames": "2.5.1",
"codemirror": "^6.0.0",
@@ -5889,9 +5889,9 @@
}
},
"node_modules/@tanstack/query-core": {
- "version": "4.40.0",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.40.0.tgz",
- "integrity": "sha512-7MJTtZkCSuehMC7IxMOCGsLvHS3jHx4WjveSrGsG1Nc1UQLjaFwwkpLA2LmPfvOAxnH4mszMOBFD6LlZE+aB+Q==",
+ "version": "5.89.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz",
+ "integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==",
"license": "MIT",
"funding": {
"type": "github",
@@ -5899,30 +5899,19 @@
}
},
"node_modules/@tanstack/react-query": {
- "version": "4.40.1",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.40.1.tgz",
- "integrity": "sha512-mgD07S5N8e5v81CArKDWrHE4LM7HxZ9k/KLeD3+NUD9WimGZgKIqojUZf/rXkfAMYZU9p0Chzj2jOXm7xpgHHQ==",
+ "version": "5.89.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz",
+ "integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==",
"license": "MIT",
"dependencies": {
- "@tanstack/query-core": "4.40.0",
- "use-sync-external-store": "^1.2.0"
+ "@tanstack/query-core": "5.89.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- },
- "react-native": {
- "optional": true
- }
+ "react": "^18 || ^19"
}
},
"node_modules/@testing-library/dom": {
diff --git a/package.json b/package.json
index 1faf5cdbd..6a9d317a2 100644
--- a/package.json
+++ b/package.json
@@ -64,7 +64,7 @@
"@openedx/paragon": "^23.5.0",
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "1.9.7",
- "@tanstack/react-query": "4.40.1",
+ "@tanstack/react-query": "5.89.0",
"@tinymce/tinymce-react": "^3.14.0",
"classnames": "2.5.1",
"codemirror": "^6.0.0",
diff --git a/src/content-tags-drawer/ContentTagsCollapsible.jsx b/src/content-tags-drawer/ContentTagsCollapsible.jsx
index 47399f8d4..c82852869 100644
--- a/src/content-tags-drawer/ContentTagsCollapsible.jsx
+++ b/src/content-tags-drawer/ContentTagsCollapsible.jsx
@@ -435,8 +435,8 @@ const ContentTagsCollapsible = ({
onKeyDown={handleSelectOnKeyDown}
ref={/** @type {React.RefObject} */(selectRef)}
isMulti
- isLoading={updateTags.isLoading}
- isDisabled={updateTags.isLoading}
+ isLoading={updateTags.isPending}
+ isDisabled={updateTags.isPending}
name="tags-select"
placeholder={intl.formatMessage(messages.collapsibleAddTagsPlaceholderText)}
isSearchable
diff --git a/src/content-tags-drawer/ContentTagsDrawer.test.jsx b/src/content-tags-drawer/ContentTagsDrawer.test.jsx
index 90fb14568..2d708509a 100644
--- a/src/content-tags-drawer/ContentTagsDrawer.test.jsx
+++ b/src/content-tags-drawer/ContentTagsDrawer.test.jsx
@@ -719,14 +719,16 @@ describe('', () => {
await waitFor(() => expect(axiosMock.history.put[0].url).toEqual(url));
expect(mockInvalidateQueries).toHaveBeenCalledTimes(5);
- expect(mockInvalidateQueries).toHaveBeenNthCalledWith(5, [
- 'contentLibrary',
- 'lib:org:lib',
- 'content',
- 'container',
- containerId,
- 'children',
- ]);
+ expect(mockInvalidateQueries).toHaveBeenNthCalledWith(5, {
+ queryKey: [
+ 'contentLibrary',
+ 'lib:org:lib',
+ 'content',
+ 'container',
+ containerId,
+ 'children',
+ ],
+ });
});
});
diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.ts
similarity index 75%
rename from src/content-tags-drawer/data/apiHooks.jsx
rename to src/content-tags-drawer/data/apiHooks.ts
index fcd8da92b..f04102f7b 100644
--- a/src/content-tags-drawer/data/apiHooks.jsx
+++ b/src/content-tags-drawer/data/apiHooks.ts
@@ -1,4 +1,3 @@
-// @ts-check
import { useMemo } from 'react';
import { getConfig } from '@edx/frontend-platform';
import {
@@ -8,6 +7,7 @@ import {
useQueryClient,
} from '@tanstack/react-query';
import { useParams } from 'react-router';
+import { TagData, TagListData } from '@src/taxonomy/data/types';
import {
getTaxonomyTagsData,
getContentTaxonomyTagsData,
@@ -17,18 +17,16 @@ import {
} from './api';
import { libraryAuthoringQueryKeys, libraryQueryPredicate, xblockQueryKeys } from '../../library-authoring/data/apiHooks';
import { getLibraryId } from '../../generic/key-utils';
-
-/** @typedef {import("../../taxonomy/data/types.js").TagListData} TagListData */
-/** @typedef {import("../../taxonomy/data/types.js").TagData} TagData */
+import { UpdateTagsData } from './types';
/**
* Builds the query to get the taxonomy tags
- * @param {number} taxonomyId The id of the taxonomy to fetch tags for
- * @param {string|null} parentTag The tag whose children we're loading, if any
- * @param {string} searchTerm The term passed in to perform search on tags
- * @param {number} numPages How many pages of tags to load at this level
+ * @param taxonomyId The id of the taxonomy to fetch tags for
+ * @param parentTag The tag whose children we're loading, if any
+ * @param searchTerm The term passed in to perform search on tags
+ * @param numPages How many pages of tags to load at this level
*/
-export const useTaxonomyTagsData = (taxonomyId, parentTag = null, numPages = 1, searchTerm = '') => {
+export const useTaxonomyTagsData = (taxonomyId: number, parentTag: string | null = null, numPages = 1, searchTerm = '') => {
const queryClient = useQueryClient();
const queryFn = async ({ queryKey }) => {
@@ -36,8 +34,7 @@ export const useTaxonomyTagsData = (taxonomyId, parentTag = null, numPages = 1,
return getTaxonomyTagsData(taxonomyId, { parentTag: parentTag || '', searchTerm, page });
};
- /** @type {{queryKey: any[], queryFn: typeof queryFn, staleTime: number}[]} */
- const queries = [];
+ const queries: { queryKey: any[]; queryFn: typeof queryFn; staleTime: number }[] = [];
for (let page = 1; page <= numPages; page++) {
queries.push(
{ queryKey: ['taxonomyTags', taxonomyId, parentTag, page, searchTerm], queryFn, staleTime: Infinity },
@@ -54,8 +51,7 @@ export const useTaxonomyTagsData = (taxonomyId, parentTag = null, numPages = 1,
const preLoadedData = new Map();
const newTags = dataPages.map(result => {
- /** @type {TagData[]} */
- const simplifiedTagsList = [];
+ const simplifiedTagsList: TagData[] = [];
result.data?.results?.forEach((tag) => {
if (tag.parentValue === parentTag) {
@@ -73,8 +69,7 @@ export const useTaxonomyTagsData = (taxonomyId, parentTag = null, numPages = 1,
// Store the pre-loaded descendants into the query cache:
preLoadedData.forEach((tags, parentValue) => {
const queryKey = ['taxonomyTags', taxonomyId, parentValue, 1, searchTerm];
- /** @type {TagListData} */
- const cachedData = {
+ const cachedData: TagListData = {
next: '',
previous: '',
count: tags.length,
@@ -101,9 +96,9 @@ export const useTaxonomyTagsData = (taxonomyId, parentTag = null, numPages = 1,
/**
* Builds the query to get the taxonomy tags applied to the content object
- * @param {string} contentId The ID of the content object to fetch the applied tags for (e.g. an XBlock usage key)
+ * @param contentId The ID of the content object to fetch the applied tags for (e.g. an XBlock usage key)
*/
-export const useContentTaxonomyTagsData = (contentId) => (
+export const useContentTaxonomyTagsData = (contentId: string) => (
useQuery({
queryKey: ['contentTaxonomyTags', contentId],
queryFn: () => getContentTaxonomyTagsData(contentId),
@@ -112,10 +107,10 @@ export const useContentTaxonomyTagsData = (contentId) => (
/**
* Builds the query to get meta data about the content object
- * @param {string} contentId The id of the content object
- * @param {boolean} enabled Flag to enable/disable the query
+ * @param contentId The id of the content object
+ * @param enabled Flag to enable/disable the query
*/
-export const useContentData = (contentId, enabled) => (
+export const useContentData = (contentId: string, enabled: boolean) => (
useQuery({
queryKey: ['contentData', contentId],
queryFn: enabled ? () => getContentData(contentId) : undefined,
@@ -125,24 +120,17 @@ export const useContentData = (contentId, enabled) => (
/**
* Builds the mutation to update the tags applied to the content object
- * @param {string} contentId The id of the content object to update tags for
+ * @param contentId The id of the content object to update tags for
*/
-export const useContentTaxonomyTagsUpdater = (contentId) => {
+export const useContentTaxonomyTagsUpdater = (contentId: string) => {
const queryClient = useQueryClient();
const unitIframe = window.frames['xblock-iframe'];
const { containerId } = useParams();
return useMutation({
- /**
- * @type {import("@tanstack/react-query").MutateFunction<
- * any,
- * any,
- * {
- * tagsData: Promise
- * }
- * >}
- */
- mutationFn: ({ tagsData }) => updateContentTaxonomyTags(contentId, tagsData),
+ mutationFn: ({ tagsData }: { tagsData: Promise }) => (
+ updateContentTaxonomyTags(contentId, tagsData)
+ ),
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] });
/// Invalidate query with pattern on course outline
@@ -157,13 +145,13 @@ export const useContentTaxonomyTagsUpdater = (contentId) => {
// Obtain library id from contentId
const libraryId = getLibraryId(contentId);
// Invalidate component metadata to update tags count
- queryClient.invalidateQueries(xblockQueryKeys.componentMetadata(contentId));
+ queryClient.invalidateQueries({ queryKey: xblockQueryKeys.componentMetadata(contentId) });
// Invalidate content search to update tags count
- queryClient.invalidateQueries(['content_search'], { predicate: (query) => libraryQueryPredicate(query, libraryId) });
+ queryClient.invalidateQueries({ queryKey: ['content_search'], predicate: (query) => libraryQueryPredicate(query, libraryId) });
// If the tags for an item were edited from a container page (Unit, Subsection, Section),
// invalidate children query to fetch count again.
if (containerId) {
- queryClient.invalidateQueries(libraryAuthoringQueryKeys.containerChildren(containerId));
+ queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.containerChildren(containerId) });
}
}
},
diff --git a/src/course-libraries/OutOfSyncAlert.tsx b/src/course-libraries/OutOfSyncAlert.tsx
index da36c4086..5a365a273 100644
--- a/src/course-libraries/OutOfSyncAlert.tsx
+++ b/src/course-libraries/OutOfSyncAlert.tsx
@@ -32,14 +32,14 @@ export const OutOfSyncAlert: React.FC = ({
onReview,
}) => {
const intl = useIntl();
- const { data, isLoading } = useEntityLinksSummaryByDownstreamContext(courseId);
+ const { data, isPending } = useEntityLinksSummaryByDownstreamContext(courseId);
const outOfSyncCount = data?.reduce((count, lib) => count + (lib.readyToSyncCount || 0), 0);
const lastPublishedDate = data?.map(lib => new Date(lib.lastPublishedAt || 0).getTime())
.reduce((acc, lastPublished) => Math.max(lastPublished, acc), 0);
const alertKey = `outOfSyncCountAlert-${courseId}`;
useEffect(() => {
- if (isLoading) {
+ if (isPending) {
return;
}
if (outOfSyncCount === 0) {
@@ -50,7 +50,7 @@ export const OutOfSyncAlert: React.FC = ({
const dismissedAlertDate = parseInt(localStorage.getItem(alertKey) ?? '0', 10);
setShowAlert((lastPublishedDate ?? 0) > dismissedAlertDate);
- }, [outOfSyncCount, lastPublishedDate, isLoading, data]);
+ }, [outOfSyncCount, lastPublishedDate, isPending, data]);
const dismissAlert = () => {
setShowAlert(false);
diff --git a/src/course-libraries/ReviewTabContent.tsx b/src/course-libraries/ReviewTabContent.tsx
index 03bbe6f2d..1d613e098 100644
--- a/src/course-libraries/ReviewTabContent.tsx
+++ b/src/course-libraries/ReviewTabContent.tsx
@@ -314,7 +314,7 @@ const ReviewTabContent = ({ courseId }: Props) => {
const intl = useIntl();
const {
data: outOfSyncItems,
- isLoading: isSyncItemsLoading,
+ isPending: isSyncItemsLoading,
isError,
error,
} = useEntityLinks({
diff --git a/src/data/apiHooks.ts b/src/data/apiHooks.ts
index 709f9d315..8c81669a3 100644
--- a/src/data/apiHooks.ts
+++ b/src/data/apiHooks.ts
@@ -8,7 +8,7 @@ import { getWaffleFlags, waffleFlagDefaults } from './api';
export const useWaffleFlags = (courseId?: string) => {
const queryClient = useQueryClient();
- const { data, isLoading, isError } = useQuery({
+ const { data, isPending: isLoading, isError } = useQuery({
queryKey: ['waffleFlags', courseId],
queryFn: () => getWaffleFlags(courseId),
// Waffle flags change rarely, so never bother refetching them:
diff --git a/src/generic/clipboard/hooks/useClipboard.ts b/src/generic/clipboard/hooks/useClipboard.ts
index 63cff384e..1542cc126 100644
--- a/src/generic/clipboard/hooks/useClipboard.ts
+++ b/src/generic/clipboard/hooks/useClipboard.ts
@@ -34,7 +34,7 @@ const useClipboard = (canEdit: boolean = true) => {
const { data: clipboardData } = useQuery({
queryKey: ['clipboard'],
queryFn: getClipboard,
- refetchInterval: (data) => (data?.content?.status === CLIPBOARD_STATUS.loading ? 1000 : false),
+ refetchInterval: (query) => (query.state.data?.content?.status === CLIPBOARD_STATUS.loading ? 1000 : false),
});
const { showToast } = useContext(ToastContext);
diff --git a/src/library-authoring/add-content/AddContent.tsx b/src/library-authoring/add-content/AddContent.tsx
index ad5023a4b..65b8d13cc 100644
--- a/src/library-authoring/add-content/AddContent.tsx
+++ b/src/library-authoring/add-content/AddContent.tsx
@@ -478,7 +478,7 @@ const AddContent = () => {
};
/* istanbul ignore next */
- if (pasteClipboardMutation.isLoading) {
+ if (pasteClipboardMutation.isPending) {
showToast(intl.formatMessage(messages.pastingClipboardMessage));
}
diff --git a/src/library-authoring/collections/LibraryCollectionPage.tsx b/src/library-authoring/collections/LibraryCollectionPage.tsx
index bfdc1d4ef..2b54615bd 100644
--- a/src/library-authoring/collections/LibraryCollectionPage.tsx
+++ b/src/library-authoring/collections/LibraryCollectionPage.tsx
@@ -112,12 +112,12 @@ const LibraryCollectionPage = () => {
const {
data: collectionData,
- isLoading,
+ isPending: isLoading,
isError,
error,
} = useCollection(libraryId, collectionId);
- const { data: libraryData, isLoading: isLibLoading } = useContentLibrary(libraryId);
+ const { data: libraryData, isPending: isLibLoading } = useContentLibrary(libraryId);
if (!collectionId || !libraryId) {
// istanbul ignore next - This shouldn't be possible; it's just here to satisfy the type checker.
diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
index 924cde59b..e1dbcea9b 100644
--- a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
+++ b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx
@@ -78,10 +78,10 @@ const ComponentAdvancedInfoInner: React.FC> = () => {
{
isEditingOLX ? (
<>
-