From 73079fc426ec6fff4c2ee0e53e9eaa4bf809942a Mon Sep 17 00:00:00 2001 From: chertik77 Date: Mon, 16 Dec 2024 17:57:45 +0000 Subject: [PATCH] fix(bug): when adding new card, cache is not updating correctly --- .../dashboard/board/cards/BoardCard.tsx | 5 +- .../board/cards/BoardCardActions.tsx | 5 +- .../board/columns/BoardColumnsActions.tsx | 9 +- .../board/columns/BoardColumnsItem.tsx | 159 +++++++++--------- .../board/columns/BoardColumnsList.tsx | 2 + src/context/dnd.context.tsx | 60 ++----- src/hooks/card/useAddCard.ts | 6 +- src/hooks/card/useCardDragHandlers.ts | 11 +- src/hooks/card/useDeleteCard.ts | 16 +- src/hooks/card/useUpdateCardsOrder.ts | 6 +- src/hooks/column/useAddColumn.ts | 2 +- src/hooks/column/useColumnDragHandlers.ts | 11 +- src/hooks/column/useDeleteColumn.ts | 13 +- src/hooks/column/useEditColumn.ts | 6 +- src/hooks/column/useUpdateColumnsOrder.ts | 2 +- 15 files changed, 128 insertions(+), 185 deletions(-) diff --git a/src/components/dashboard/board/cards/BoardCard.tsx b/src/components/dashboard/board/cards/BoardCard.tsx index 1a81b431..d4e5dd5a 100644 --- a/src/components/dashboard/board/cards/BoardCard.tsx +++ b/src/components/dashboard/board/cards/BoardCard.tsx @@ -1,6 +1,5 @@ import type { Card } from 'types' -import { memo } from 'react' import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' @@ -10,7 +9,7 @@ import { BoardCardActions } from './BoardCardActions' import { BoardCardDeadline } from './BoardCardDeadline' import { BoardCardPriority } from './BoardCardPriority' -export const BoardCard = memo(({ card }: { card: Card }) => { +export const BoardCard = ({ card }: { card: Card }) => { const { setNodeRef, attributes, @@ -64,4 +63,4 @@ export const BoardCard = memo(({ card }: { card: Card }) => { ) -}) +} diff --git a/src/components/dashboard/board/cards/BoardCardActions.tsx b/src/components/dashboard/board/cards/BoardCardActions.tsx index 20cccc72..b3efe968 100644 --- a/src/components/dashboard/board/cards/BoardCardActions.tsx +++ b/src/components/dashboard/board/cards/BoardCardActions.tsx @@ -1,16 +1,17 @@ import type { Card } from 'types' -import { useDragAndDrop } from 'context/dnd.context' import { isToday } from 'date-fns' import { useModal } from 'react-modal-state' import { EditCardModal } from 'components/dashboard/modals' import { Button } from 'components/ui' +import { useDeleteCard } from 'hooks/card' + export const BoardCardActions = ({ card }: { card: Card }) => { const { open } = useModal(EditCardModal) - const { deleteCard } = useDragAndDrop() + const { mutate: deleteCard } = useDeleteCard() return (
diff --git a/src/components/dashboard/board/columns/BoardColumnsActions.tsx b/src/components/dashboard/board/columns/BoardColumnsActions.tsx index 26d04ba0..7bc37d46 100644 --- a/src/components/dashboard/board/columns/BoardColumnsActions.tsx +++ b/src/components/dashboard/board/columns/BoardColumnsActions.tsx @@ -2,13 +2,12 @@ import type { onSaveProps } from 'react-edit-text' import type { Column } from 'types' import { useState } from 'react' -import { useDragAndDrop } from 'context/dnd.context' import { EditText } from 'react-edit-text' import { toast } from 'sonner' import { Button } from 'components/ui' -import { useEditColumn } from 'hooks/column' +import { useDeleteColumn, useEditColumn } from 'hooks/column' import { DEFAULT_COLUMN_TITLE, @@ -20,9 +19,9 @@ import { cn } from 'lib' export const BoardColumnsActions = ({ column }: { column: Column }) => { const [columnTitle, setColumnTitle] = useState(column.title) - const { deleteColumn } = useDragAndDrop() + const { mutate: deleteColumn } = useDeleteColumn() - const { mutate } = useEditColumn() + const { mutate: editColumn } = useEditColumn() const handleColumnEdit = ({ value, previousValue }: onSaveProps) => { if (value.trim().length < REQUIRED_COLUMN_TITLE_LENGTH) { @@ -30,7 +29,7 @@ export const BoardColumnsActions = ({ column }: { column: Column }) => { return toast.error('Column title must be at least 3 characters long.') } - mutate({ columnId: column.id, data: { title: value } }) + editColumn({ columnId: column.id, data: { title: value } }) } return ( diff --git a/src/components/dashboard/board/columns/BoardColumnsItem.tsx b/src/components/dashboard/board/columns/BoardColumnsItem.tsx index ab4c5e40..714e3790 100644 --- a/src/components/dashboard/board/columns/BoardColumnsItem.tsx +++ b/src/components/dashboard/board/columns/BoardColumnsItem.tsx @@ -1,6 +1,5 @@ import type { Card, Column } from 'types' -import { memo } from 'react' import { SortableContext, useSortable, @@ -29,88 +28,90 @@ type BoardColumnsItemProps = { backgroundIdentifier?: string } -export const BoardColumnsItem = memo( - ({ column, cards, backgroundIdentifier }: BoardColumnsItemProps) => { - const { open } = useModal(NewCardModal) +export const BoardColumnsItem = ({ + column, + cards, + backgroundIdentifier +}: BoardColumnsItemProps) => { + const { open } = useModal(NewCardModal) - const { cardPriority, cardDeadline } = useCardFilters() + const { cardPriority, cardDeadline } = useCardFilters() - const isTabletAndBelow = useTabletAndBelowMediaQuery() + const isTabletAndBelow = useTabletAndBelowMediaQuery() - const { cardsIds } = useDragAndDrop() + const { cardsIds } = useDragAndDrop() - const filteredCards = getFilteredCards(cards!, { - priority: cardPriority, - deadline: cardDeadline - }) + const filteredCards = getFilteredCards(cards!, { + priority: cardPriority, + deadline: cardDeadline + }) - const { - setNodeRef, - attributes, - listeners, - transition, - transform, - isDragging - } = useSortable({ - id: column.id, - data: { type: 'column', column } - }) + const { + setNodeRef, + attributes, + listeners, + transition, + transform, + isDragging + } = useSortable({ + id: column.id, + data: { type: 'column', column } + }) - const style = { - transition, - transform: CSS.Transform.toString(transform) - } - - return isDragging ? ( -
- ) : ( -
- - - - - {filteredCards?.map(card => ( - - ))} - - - - - -
- ) + const style = { + transition, + transform: CSS.Transform.toString(transform) } -) + + return isDragging ? ( +
+ ) : ( +
+ + + + + {filteredCards?.map(card => ( + + ))} + + + + + +
+ ) +} diff --git a/src/components/dashboard/board/columns/BoardColumnsList.tsx b/src/components/dashboard/board/columns/BoardColumnsList.tsx index 6903a519..a0b011d2 100644 --- a/src/components/dashboard/board/columns/BoardColumnsList.tsx +++ b/src/components/dashboard/board/columns/BoardColumnsList.tsx @@ -16,6 +16,8 @@ export const BoardColumnsList = ({ }: BoardColumnsListProps) => { const { columns, cards, columnsIds } = useDragAndDrop() + console.log(cards) + return (
> + setCards: Dispatch> columns: Column[] | undefined cards: Card[] | undefined columnsIds: string[] | undefined cardsIds: string[] | undefined - deleteColumn: (columnId: string) => void - deleteCard: (cardId: string) => void } -const DragAndDropContext = createContext(null) - type DragAndDropProviderProps = { children: ReactNode initialColumns: Column[] | undefined } +const DragAndDropContext = createContext(null) + export const DragAndDropProvider = ({ children, initialColumns @@ -66,29 +59,6 @@ export const DragAndDropProvider = ({ setActiveColumn }) - const { mutate: deleteColumnMutation } = useDeleteColumn() - const { mutate: deleteCardMutation } = useDeleteCard() - - const deleteColumn = useCallback( - (columnId: string) => { - setColumns(columns?.filter(col => col.id !== columnId)) - - setCards(cards?.filter(c => c.columnId !== columnId)) - - deleteColumnMutation(columnId) - }, - [columns, cards, deleteColumnMutation] - ) - - const deleteCard = useCallback( - (cardId: string) => { - setCards(cards?.filter(c => c.id !== cardId)) - - deleteCardMutation(cardId) - }, - [cards, deleteCardMutation] - ) - const onDragStart = (event: DragStartEvent) => { if (!event.active) return @@ -122,17 +92,9 @@ export const DragAndDropProvider = ({ }) ) - const contextValue: DragAndDropContext = { - columns, - cards, - cardsIds, - columnsIds, - deleteColumn, - deleteCard - } - return ( - + ) => { const queryClient = useQueryClient() - const boardId = useGetBoardId() - const { data: column } = useModalInstance() const { close } = useModal(NewCardModal) @@ -25,7 +21,7 @@ export const useAddCard = (reset: UseFormReset) => { mutationKey: [CacheKeys.AddCard], mutationFn: (data: CardSchema) => cardService.addNewCard(column, data), onSuccess() { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) close() reset() }, diff --git a/src/hooks/card/useCardDragHandlers.ts b/src/hooks/card/useCardDragHandlers.ts index 505ca15a..92e53838 100644 --- a/src/hooks/card/useCardDragHandlers.ts +++ b/src/hooks/card/useCardDragHandlers.ts @@ -3,22 +3,19 @@ import type { Dispatch, SetStateAction } from 'react' import type { Card } from 'types' import { arrayMove } from '@dnd-kit/sortable' +import { type DragAndDropContext } from 'context/dnd.context' import { findIndexById } from 'lib' import { useUpdateCardsOrder } from './useUpdateCardsOrder' -type UseCardDragHandlersProps = { - cards: Card[] | undefined - setCards: Dispatch> - setActiveCard: Dispatch> -} - export const useCardDragHandlers = ({ cards, setCards, setActiveCard -}: UseCardDragHandlersProps) => { +}: Pick & { + setActiveCard: Dispatch> +}) => { const { mutate: updateCardsOrder } = useUpdateCardsOrder() const onDragStart = ({ active }: DragStartEvent) => { diff --git a/src/hooks/card/useDeleteCard.ts b/src/hooks/card/useDeleteCard.ts index 03b6ee7f..71b9f983 100644 --- a/src/hooks/card/useDeleteCard.ts +++ b/src/hooks/card/useDeleteCard.ts @@ -1,7 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' -import { toast } from 'sonner' - -import { useGetBoardId } from 'hooks/board' +import { useDragAndDrop } from 'context/dnd.context' import { CacheKeys } from 'config' import { cardService } from 'services' @@ -9,18 +7,16 @@ import { cardService } from 'services' export const useDeleteCard = () => { const queryClient = useQueryClient() - const boardId = useGetBoardId() + const { setCards } = useDragAndDrop() return useMutation({ mutationKey: [CacheKeys.DeleteCard], mutationFn: (cardId: string) => cardService.deleteCard(cardId), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + onMutate: async cardId => { + setCards(prevCards => prevCards?.filter(c => c.id !== cardId)) }, - onError: () => { - toast.error( - 'An error occurred while deleting the task. Our technical team has been notified. Please try again shortly.' - ) + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) } }) } diff --git a/src/hooks/card/useUpdateCardsOrder.ts b/src/hooks/card/useUpdateCardsOrder.ts index 878b2363..9233c290 100644 --- a/src/hooks/card/useUpdateCardsOrder.ts +++ b/src/hooks/card/useUpdateCardsOrder.ts @@ -3,22 +3,18 @@ import type { UpdateOrderData } from 'types' import { useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { useGetBoardId } from 'hooks/board' - import { CacheKeys } from 'config' import { cardService } from 'services' export const useUpdateCardsOrder = () => { const queryClient = useQueryClient() - const boardId = useGetBoardId() - return useMutation({ mutationKey: [CacheKeys.UpdateCardsOrder], mutationFn: ({ columnId, ids }: UpdateOrderData & { columnId: string }) => cardService.updateCardsOrder(columnId, { ids }), onSuccess() { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) }, onError() { toast.error( diff --git a/src/hooks/column/useAddColumn.ts b/src/hooks/column/useAddColumn.ts index b5cd4dee..5acf7905 100644 --- a/src/hooks/column/useAddColumn.ts +++ b/src/hooks/column/useAddColumn.ts @@ -17,7 +17,7 @@ export const useAddColumn = () => { mutationFn: () => columnService.addNewColumn(boardId, { title: DEFAULT_COLUMN_TITLE }), onSuccess() { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) }, onError() { toast.error( diff --git a/src/hooks/column/useColumnDragHandlers.ts b/src/hooks/column/useColumnDragHandlers.ts index f76c6498..cf6c2b83 100644 --- a/src/hooks/column/useColumnDragHandlers.ts +++ b/src/hooks/column/useColumnDragHandlers.ts @@ -3,22 +3,19 @@ import type { Dispatch, SetStateAction } from 'react' import type { Column } from 'types' import { arrayMove } from '@dnd-kit/sortable' +import { type DragAndDropContext } from 'context/dnd.context' import { findIndexById } from 'lib' import { useUpdateColumnsOrder } from './useUpdateColumnsOrder' -type UseCardDragHandlersProps = { - columns: Column[] | undefined - setColumns: Dispatch> - setActiveColumn: Dispatch> -} - export const useColumnDragHandlers = ({ columns, setColumns, setActiveColumn -}: UseCardDragHandlersProps) => { +}: Pick & { + setActiveColumn: Dispatch> +}) => { const { mutate: updateColumnsOrder } = useUpdateColumnsOrder() const onDragStart = ({ active }: DragStartEvent) => { diff --git a/src/hooks/column/useDeleteColumn.ts b/src/hooks/column/useDeleteColumn.ts index 9a9268cd..a11e62d0 100644 --- a/src/hooks/column/useDeleteColumn.ts +++ b/src/hooks/column/useDeleteColumn.ts @@ -1,5 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' -import { toast } from 'sonner' +import { useDragAndDrop } from 'context/dnd.context' import { useGetBoardId } from 'hooks/board' @@ -9,18 +9,19 @@ import { columnService } from 'services' export const useDeleteColumn = () => { const queryClient = useQueryClient() + const { setColumns, setCards } = useDragAndDrop() + const boardId = useGetBoardId() return useMutation({ mutationKey: [CacheKeys.DeleteColumn], mutationFn: (columnId: string) => columnService.deleteColumn(columnId), + onMutate: async columnId => { + setColumns(prevColumns => prevColumns?.filter(c => c.id !== columnId)) + setCards(prevCards => prevCards?.filter(c => c.columnId !== columnId)) + }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) - }, - onError: () => { - toast.error( - 'Unexpected error during column deletion. We apologize for the inconvenience. Please try again later.' - ) } }) } diff --git a/src/hooks/column/useEditColumn.ts b/src/hooks/column/useEditColumn.ts index 134e9afa..cca7999d 100644 --- a/src/hooks/column/useEditColumn.ts +++ b/src/hooks/column/useEditColumn.ts @@ -3,22 +3,18 @@ import type { ColumnTitle } from 'types' import { useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { useGetBoardId } from 'hooks/board' - import { CacheKeys } from 'config' import { columnService } from 'services' export const useEditColumn = () => { const queryClient = useQueryClient() - const boardId = useGetBoardId() - return useMutation({ mutationKey: [CacheKeys.EditColumn], mutationFn: ({ columnId, data }: { columnId: string; data: ColumnTitle }) => columnService.editColumn(columnId, data), onSuccess() { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) }, onError() { toast.error( diff --git a/src/hooks/column/useUpdateColumnsOrder.ts b/src/hooks/column/useUpdateColumnsOrder.ts index 46b8fb48..d4b4a255 100644 --- a/src/hooks/column/useUpdateColumnsOrder.ts +++ b/src/hooks/column/useUpdateColumnsOrder.ts @@ -18,7 +18,7 @@ export const useUpdateColumnsOrder = () => { mutationFn: ({ ids }: UpdateOrderData) => columnService.updateColumnsOrder(boardId, { ids }), onSuccess() { - queryClient.invalidateQueries({ queryKey: [CacheKeys.Board, boardId] }) + queryClient.invalidateQueries({ queryKey: [CacheKeys.Board] }) }, onError() { toast.error(