Skip to content

Commit

Permalink
feat: add ability to invalidateQueries through meta in mutation cache
Browse files Browse the repository at this point in the history
  • Loading branch information
chertik77 committed Jan 14, 2025
1 parent 5928685 commit 708a832
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 49 deletions.
6 changes: 2 additions & 4 deletions src/features/kanban/board/hooks/useAddBoard.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { UseFormReset } from 'react-hook-form'
import type { BoardSchema } from '../board.schema'

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { useModal } from 'react-modal-state'
import { toast } from 'sonner'
Expand All @@ -13,18 +13,16 @@ import { BoardCacheKeys } from '../config'
export const useAddBoard = (reset: UseFormReset<BoardSchema>) => {
const navigate = useNavigate()

const queryClient = useQueryClient()

const { close: closeNewBoardModal } = useModal(NewBoardModal)

return useMutation({
mutationKey: [BoardCacheKeys.AddBoard],
mutationFn: boardService.addNewBoard,
meta: { invalidates: [[BoardCacheKeys.Boards]] },
onSuccess(data) {
closeNewBoardModal()
reset()
navigate({ to: `/dashboard/$boardId`, params: { boardId: data.id } })
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Boards] })
},
onError() {
toast.error(
Expand Down
6 changes: 2 additions & 4 deletions src/features/kanban/card/hooks/useAddCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { UseFormReset } from 'react-hook-form'
import type { CardSchema } from '../card.schema'
import type { AddCardModalProps } from '../card.types'

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { useModal, useModalInstance } from 'react-modal-state'
import { toast } from 'sonner'

Expand All @@ -13,8 +13,6 @@ import { AddCardModal } from '../components/modals'
import { CardCacheKeys } from '../config'

export const useAddCard = (reset: UseFormReset<CardSchema>) => {
const queryClient = useQueryClient()

const {
data: { columnId }
} = useModalInstance<AddCardModalProps>()
Expand All @@ -24,8 +22,8 @@ export const useAddCard = (reset: UseFormReset<CardSchema>) => {
return useMutation({
mutationKey: [CardCacheKeys.AddCard],
mutationFn: (data: CardSchema) => cardService.addNewCard(columnId, data),
meta: { invalidates: [[BoardCacheKeys.Board]] },
onSuccess() {
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Board] })
closeAddCardModal()
reset()
},
Expand Down
8 changes: 2 additions & 6 deletions src/features/kanban/card/hooks/useDeleteCard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'

import { BoardCacheKeys } from 'features/kanban/board/config'
import { useDragAndDrop } from 'features/kanban/dnd/hooks'
Expand All @@ -7,18 +7,14 @@ import { cardService } from '../card.service'
import { CardCacheKeys } from '../config'

export const useDeleteCard = () => {
const queryClient = useQueryClient()

const { setCards } = useDragAndDrop()

return useMutation({
mutationKey: [CardCacheKeys.DeleteCard],
mutationFn: (cardId: string) => cardService.deleteCard(cardId),
meta: { invalidates: [[BoardCacheKeys.Board]] },
onMutate: async cardId => {
setCards(prevCards => prevCards?.filter(c => c.id !== cardId))
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Board] })
}
})
}
13 changes: 4 additions & 9 deletions src/features/kanban/card/hooks/useUpdateCardsOrder.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import type { UpdateOrderData } from 'features/kanban/shared/types'

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import { BoardCacheKeys } from 'features/kanban/board/config'

import { cardService } from '../card.service'
import { CardCacheKeys } from '../config'

export const useUpdateCardsOrder = () => {
const queryClient = useQueryClient()

return useMutation({
export const useUpdateCardsOrder = () =>
useMutation({
mutationKey: [CardCacheKeys.UpdateCardsOrder],
mutationFn: ({ columnId, ids }: UpdateOrderData & { columnId: string }) =>
cardService.updateCardsOrder(columnId, { ids }),
onSuccess() {
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Board] })
},
meta: { invalidates: [[BoardCacheKeys.Board]] },
onError() {
toast.error(
'Unexpected error during cards reordering. We apologize for the inconvenience. Please try again later.'
)
}
})
}
6 changes: 2 additions & 4 deletions src/features/kanban/column/hooks/useAddColumn.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { UseFormReset } from 'react-hook-form'

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { useModal } from 'react-modal-state'
import { toast } from 'sonner'

Expand All @@ -13,8 +13,6 @@ import { AddColumnModal } from '../components/modals'
import { ColumnCacheKeys } from '../config'

export const useAddColumn = (reset: UseFormReset<TitleSchema>) => {
const queryClient = useQueryClient()

const { close: closeAddColumnModal } = useModal(AddColumnModal)

const { boardId } = useGetParamBoardId()
Expand All @@ -23,10 +21,10 @@ export const useAddColumn = (reset: UseFormReset<TitleSchema>) => {
mutationKey: [ColumnCacheKeys.AddColumn],
mutationFn: ({ title }: TitleSchema) =>
columnService.addNewColumn(boardId!, { title }),
meta: { invalidates: [[BoardCacheKeys.Board]] },
onSuccess() {
closeAddColumnModal()
reset()
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Board] })
},
onError() {
toast.error(
Expand Down
13 changes: 2 additions & 11 deletions src/features/kanban/column/hooks/useDeleteColumn.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'

import { BoardCacheKeys } from 'features/kanban/board/config'
import { useGetParamBoardId } from 'features/kanban/board/hooks'
import { useDragAndDrop } from 'features/kanban/dnd/hooks'

import { columnService } from '../column.service'
import { ColumnCacheKeys } from '../config'

export const useDeleteColumn = () => {
const queryClient = useQueryClient()

const { setColumns, setCards } = useDragAndDrop()

const { boardId } = useGetParamBoardId()

return useMutation({
mutationKey: [ColumnCacheKeys.DeleteColumn],
mutationFn: (columnId: string) => columnService.deleteColumn(columnId),
meta: { invalidates: [[BoardCacheKeys.Board]] },
onMutate: async columnId => {
setColumns(prevColumns => prevColumns?.filter(c => c.id !== columnId))
setCards(prevCards => prevCards?.filter(c => c.columnId !== columnId))
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [BoardCacheKeys.Board, boardId]
})
}
})
}
8 changes: 2 additions & 6 deletions src/features/kanban/column/hooks/useUpdateColumnsOrder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { UpdateOrderData } from 'features/kanban/shared/types'

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import { BoardCacheKeys } from 'features/kanban/board/config'
Expand All @@ -10,17 +10,13 @@ import { columnService } from '../column.service'
import { ColumnCacheKeys } from '../config'

export const useUpdateColumnsOrder = () => {
const queryClient = useQueryClient()

const { boardId } = useGetParamBoardId()

return useMutation({
mutationKey: [ColumnCacheKeys.UpdateColumnsOrder],
mutationFn: ({ ids }: UpdateOrderData) =>
columnService.updateColumnsOrder(boardId!, { ids }),
onSuccess() {
queryClient.invalidateQueries({ queryKey: [BoardCacheKeys.Board] })
},
meta: { invalidates: [[BoardCacheKeys.Board]] },
onError() {
toast.error(
'Unexpected error during columns reordering. We apologize for the inconvenience. Please try again later.'
Expand Down
6 changes: 2 additions & 4 deletions src/features/user/hooks/useEditProfile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { useModal } from 'react-modal-state'
import { toast } from 'sonner'

Expand All @@ -7,17 +7,15 @@ import { UserCacheKeys } from '../config'
import { userService } from '../user.service'

export const useEditProfile = () => {
const queryClient = useQueryClient()

const { close: closeEditProfileModal } = useModal(EditProfileModal)

return useMutation({
mutationKey: [UserCacheKeys.EditUserProfile],
mutationFn: userService.updateUserCredentials,
meta: { invalidates: [[UserCacheKeys.User]] },
onSuccess() {
closeEditProfileModal()
toast.success('Your profile has been successfully updated.')
queryClient.invalidateQueries({ queryKey: [UserCacheKeys.User] })
},
onError(e) {
toast.error(
Expand Down
21 changes: 20 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import type { QueryKey } from '@tanstack/react-query'
import type { AxiosError } from 'axios'

import { StrictMode } from 'react'
import { GoogleOAuthProvider } from '@react-oauth/google'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import {
matchQuery,
MutationCache,
QueryClient,
QueryClientProvider
} from '@tanstack/react-query'
import { createRouter, RouterProvider } from '@tanstack/react-router'
import ReactDOM from 'react-dom/client'

Expand All @@ -13,6 +19,16 @@ import 'react-responsive-modal/styles.css'
import './index.css'

const queryClient = new QueryClient({
mutationCache: new MutationCache({
onSuccess: (_data, _variables, _context, mutation) => {
queryClient.invalidateQueries({
predicate: query =>
mutation.meta?.invalidates?.some(queryKey =>
matchQuery({ queryKey }, query)
) ?? false
})
}
}),
defaultOptions: {
queries: { refetchOnWindowFocus: false }
}
Expand All @@ -23,6 +39,9 @@ const router = createRouter({ routeTree, defaultPendingMinMs: 0 })
declare module '@tanstack/react-query' {
interface Register {
defaultError: AxiosError
mutationMeta: {
invalidates?: QueryKey[]
}
}
}

Expand Down

0 comments on commit 708a832

Please sign in to comment.