Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion frontends/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"ol-test-utilities": "0.0.0"
},
"dependencies": {
"@lukemorales/query-key-factory": "^1.3.2",
"@tanstack/react-query": "^4.36.1",
"axios": "^1.6.3"
}
Expand Down
8 changes: 4 additions & 4 deletions frontends/api/src/hooks/articles/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { renderHook, waitFor } from "@testing-library/react"

import { setupReactQueryTest } from "../test-utils"
import keyFactory from "./keyFactory"
import { articleKeys } from "./queries"
import { setMockResponse, urls, makeRequest } from "../../test-utils"
import { UseQueryResult } from "@tanstack/react-query"
import { articles as factory } from "../../test-utils/factories"
Expand Down Expand Up @@ -72,7 +72,7 @@ describe("Article CRUD", () => {
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(makeRequest).toHaveBeenCalledWith("post", url, requestData)
expect(queryClient.invalidateQueries).toHaveBeenCalledWith(
keyFactory.list._def,
articleKeys.listRoot(),
)
})

Expand All @@ -89,7 +89,7 @@ describe("Article CRUD", () => {
await waitFor(() => expect(result.current.isSuccess).toBe(true))
const { id, ...patchData } = article
expect(makeRequest).toHaveBeenCalledWith("patch", url, patchData)
expect(queryClient.invalidateQueries).toHaveBeenCalledWith(keyFactory._def)
expect(queryClient.invalidateQueries).toHaveBeenCalledWith(articleKeys.root)
})

test("useArticleDestroy calls correct API", async () => {
Expand All @@ -105,7 +105,7 @@ describe("Article CRUD", () => {
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(makeRequest).toHaveBeenCalledWith("delete", url, undefined)
expect(queryClient.invalidateQueries).toHaveBeenCalledWith(
keyFactory.list._def,
articleKeys.listRoot(),
)
})
})
12 changes: 6 additions & 6 deletions frontends/api/src/hooks/articles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import type {
ArticlesApiArticlesListRequest as ArticleListRequest,
Article,
} from "../../generated/v1"
import articles from "./keyFactory"
import { articleQueries, articleKeys } from "./queries"

const useArticleList = (
params: ArticleListRequest = {},
opts: Pick<UseQueryOptions, "enabled"> = {},
) => {
return useQuery({
...articles.list(params),
...articleQueries.list(params),
...opts,
})
}
Expand All @@ -27,7 +27,7 @@ const useArticleList = (
*/
const useArticleDetail = (id: number | undefined) => {
return useQuery({
...articles.detail(id ?? -1),
...articleQueries.detail(id ?? -1),
enabled: id !== undefined,
})
}
Expand All @@ -40,7 +40,7 @@ const useArticleCreate = () => {
.articlesCreate({ ArticleRequest: data })
.then((response) => response.data),
onSuccess: () => {
client.invalidateQueries(articles.list._def)
client.invalidateQueries(articleKeys.listRoot())
},
})
}
Expand All @@ -49,7 +49,7 @@ const useArticleDestroy = () => {
return useMutation({
mutationFn: (id: number) => articlesApi.articlesDestroy({ id }),
onSuccess: () => {
client.invalidateQueries(articles.list._def)
client.invalidateQueries(articleKeys.listRoot())
},
})
}
Expand All @@ -64,7 +64,7 @@ const useArticlePartialUpdate = () => {
})
.then((response) => response.data),
onSuccess: (_data) => {
client.invalidateQueries(articles._def)
client.invalidateQueries(articleKeys.root)
},
})
}
Expand Down
19 changes: 0 additions & 19 deletions frontends/api/src/hooks/articles/keyFactory.ts

This file was deleted.

27 changes: 27 additions & 0 deletions frontends/api/src/hooks/articles/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { QueryOptions } from "@tanstack/react-query"
import { articlesApi } from "../../clients"
import type { ArticlesApiArticlesListRequest as ArticleListRequest } from "../../generated/v1"

const articleKeys = {
root: ["articles"],
listRoot: () => [...articleKeys.root, "list"],
list: (params: ArticleListRequest) => [...articleKeys.listRoot(), params],
detailRoot: () => [...articleKeys.root, "detail"],
detail: (id: number) => [...articleKeys.detailRoot(), id],
}
Copy link
Contributor Author

@ChristopherChudzicki ChristopherChudzicki Feb 11, 2025

Choose a reason for hiding this comment

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

The structure above (and in other queries files) is based on https://tkdodo.eu/blog/effective-react-query-keys#use-query-key-factories (blog by one of the maintainers).

Still a "key factory", but a little less automated than it was with @lukemorales/query-key-factory.

The main downside is that, in contrast to @lukemorales/query-key-factory, we are now responsible for ensuring the keys are unique.


const articleQueries = {
list: (params: ArticleListRequest) =>
({
queryKey: articleKeys.list(params),
queryFn: () => articlesApi.articlesList(params).then((res) => res.data),
}) satisfies QueryOptions,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't updated to v5 in this PR, but once we updated to v5 (which should be easy now that @lukemorales/query-key-factory is gone), all these satisfies QueryOptions should be replaced with https://tanstack.com/query/latest/docs/framework/react/reference/queryOptions

detail: (id: number) =>
({
queryKey: articleKeys.detail(id),
queryFn: () =>
articlesApi.articlesRetrieve({ id }).then((res) => res.data),
}) satisfies QueryOptions,
}

export { articleQueries, articleKeys }
12 changes: 6 additions & 6 deletions frontends/api/src/hooks/channels/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ import type {
ChannelsApiChannelsListRequest,
PatchedChannelWriteRequest,
} from "../../generated/v0"
import channels from "./keyFactory"
import { channelKeys, channelQueries } from "./queries"

const useChannelsList = (
params: ChannelsApiChannelsListRequest = {},
opts: Pick<UseQueryOptions, "enabled"> = {},
) => {
return useQuery({
...channels.list(params),
...channelQueries.list(params),
...opts,
})
}

const useChannelDetail = (channelType: string, channelName: string) => {
return useQuery({
...channels.detailByType(channelType, channelName),
...channelQueries.detailByType(channelType, channelName),
})
}

const useChannelCounts = (channelType: string) => {
return useQuery({
...channels.countsByType(channelType),
...channelQueries.countsByType(channelType),
})
}

Expand All @@ -45,7 +45,7 @@ const useChannelPartialUpdate = () => {
})
.then((response) => response.data),
onSuccess: (_data) => {
client.invalidateQueries(channels._def)
client.invalidateQueries(channelKeys.root)
},
})
}
Expand All @@ -55,5 +55,5 @@ export {
useChannelsList,
useChannelPartialUpdate,
useChannelCounts,
channels,
channelQueries,
}
34 changes: 0 additions & 34 deletions frontends/api/src/hooks/channels/keyFactory.ts

This file was deleted.

55 changes: 55 additions & 0 deletions frontends/api/src/hooks/channels/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { QueryOptions } from "@tanstack/react-query"
import { channelsApi } from "../../clients"
import type { ChannelsApiChannelsListRequest as FieldsApiListRequest } from "../../generated/v0"

const channelKeys = {
root: ["channel"],
detailRoot: () => [...channelKeys.root, "detail"],
detail: (id: number) => [...channelKeys.detailRoot(), id],
detailByType: (channelType: string, name: string) => [
...channelKeys.detailRoot(),
channelType,
name,
],
listRoot: () => [...channelKeys.root, "list"],
list: (params: FieldsApiListRequest) => [...channelKeys.listRoot(), params],
countsByType: (channelType: string) => [
...channelKeys.root,
"counts",
channelType,
],
}

const channelQueries = {
list: (params: FieldsApiListRequest) =>
({
queryKey: channelKeys.list(params),
queryFn: () => channelsApi.channelsList(params).then((res) => res.data),
}) satisfies QueryOptions,
detail: (id: number) =>
({
queryKey: channelKeys.detail(id),
queryFn: () =>
channelsApi.channelsRetrieve({ id }).then((res) => res.data),
}) satisfies QueryOptions,
detailByType: (channelType: string, name: string) =>
({
queryKey: channelKeys.detailByType(channelType, name),
queryFn: () => {
return channelsApi
.channelsTypeRetrieve({ channel_type: channelType, name: name })
.then((res) => res.data)
},
}) satisfies QueryOptions,
countsByType: (channelType: string) =>
({
queryKey: channelKeys.countsByType(channelType),
queryFn: () => {
return channelsApi
.channelsCountsList({ channel_type: channelType })
.then((res) => res.data)
},
}) satisfies QueryOptions,
}

export { channelQueries, channelKeys }
9 changes: 4 additions & 5 deletions frontends/api/src/hooks/learningPaths/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LearningResource } from "../../generated/v1"
import * as factories from "../../test-utils/factories"
import { setupReactQueryTest } from "../test-utils"
import { setMockResponse, urls, makeRequest } from "../../test-utils"
import keyFactory from "../learningResources/keyFactory"
import { learningResourceKeys } from "../learningResources/queries"
import {
useLearningPathsDetail,
useLearningPathsList,
Expand All @@ -14,7 +14,7 @@ import {
useLearningPathDestroy,
useLearningPathUpdate,
} from "./index"
import learningPathKeyFactory from "./keyFactory"
import { learningPathKeys } from "./queries"

const factory = factories.learningResources

Expand Down Expand Up @@ -115,9 +115,8 @@ describe("LearningPath CRUD", () => {
const path = factory.learningPath()
const relationship = factory.learningPathRelationship({ parent: path.id })
const keys = {
learningResources: keyFactory._def,
relationshipListing: learningPathKeyFactory.detail(path.id)._ctx
.infiniteItems._def,
learningResources: learningResourceKeys.root,
relationshipListing: learningPathKeys.infiniteItemsRoot(path.id),
}
const pathUrls = {
list: urls.learningPaths.list(),
Expand Down
Loading
Loading