Next.js Discord

Discord Forum

React-Hook Form SetQueryData doesnt show in ui

Answered
Saltwater Crocodile posted this in #help-forum
Open in Discord
Saltwater CrocodileOP
Hello Guys i currently have an issue with my Trello Clone Drag and Drop.

In one component i update the list locally and pass it in the values after that mutateAsync gets called:
const updatedLists = lists.map((list) => {
      if (activeListPosition > overListPosition) {
        if (
          list.position >= overListPosition &&
          list.position < activeListPosition
        ) {
          return { ...list, position: list.position + 1 };
        } else if (list.id === activeListId) {
          return { ...list, position: overListPosition };
        }
      } else if (activeListPosition < overListPosition) {
        if (
          list.position <= overListPosition &&
          list.position > activeListPosition
        ) {
          return { ...list, position: list.position - 1 };
        } else if (list.id === activeListId) {
          return { ...list, position: overListPosition };
        }
      }
      return list;
    });

    const values = {
      projectId,
      activeListId,
      overListId,
      activeListPosition,
      overListPosition,
      token,
      updatedLists,
    };

    mutateAsync(values);

In here i make an optimistic update with the getLists and pass the updsatedLists:
const { mutateAsync } = useMutation({
    mutationFn: useMoveList,
    onMutate: async (values) => {
      await queryClient.cancelQueries(['getLists']);

      queryClient.getQueryData(['getLists']);

      console.log('UPDATED LISTS: ', values.updatedLists);

      queryClient.setQueryData(['getLists'], { data: values.updatedLists });

      return { prevList: lists };
    },
    onError: (_, __, context) => {
      toast.error('Failed');
      queryClient.setQueryData(['getLists'], () => context?.prevList);
    },
    onSettled: () => {
      // queryClient.invalidateQueries({ queryKey: ['getLists'] });
    },
    onSuccess: () => {
      toast.success('Moved');
    },
  });

Now when console logging i get the updatedList in the compoentn but it doesnt show in ui:
const { data: list, isLoading: listIsLoading } = useGetLists(
    token,
    projectId,
  );
const lists: List[] = list?.data;

  console.log('LIST DATA: ', list?.data);

here is my useGetLists hook:
import { BACKEND_URL } from "@/lib/constants";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";

export const useGetLists = (token: string | undefined, projectId: string) => {
    return useQuery({
        queryKey: ["getLists"],
        queryFn: async () => {
            return await axios.get(BACKEND_URL + '/project/list/' + projectId, {
                headers: {
                    'Content-Type': 'application/json',
                    Accept: 'application/json',
                    Authorization: "Bearer " + token
                },
            });
        },
    });
}

Does anyone know why it doesnt show directly in the ui?
Answered by Ray
 queryClient.setQueryData(['getLists'], values.updatedLists.sort(
        (a, b) => a.position - b.position,
      ));
View full answer

122 Replies

Saltwater CrocodileOP
Please @ me on responses. Thank you
@Saltwater Crocodile Please @ me on responses. Thank you
try
 onMutate: async (values) => {
      await queryClient.cancelQueries(['getLists']);

      const prevList = queryClient.getQueryData(['getLists']);

      console.log('UPDATED LISTS: ', values.updatedLists);

      queryClient.setQueryData(['getLists'], values.updatedLists);

      return { prevList };
    },
Saltwater CrocodileOP
When i setQueryData without {data: values.updatedValues} i get following error in the page:
@Ray
WHen console logging the list.data after Drag and Drop it is undefined
When doig it like that:
queryClient.setQueryData(['getLists'], { data: values.updatedLists });

i get the correct values in list.data but it doesnt show in the ui
@Saltwater Crocodile When doig it like that: js queryClient.setQueryData(['getLists'], { data: values.updatedLists }); i get the correct values in list.data but it doesnt show in the ui
ok change this
import { BACKEND_URL } from "@/lib/constants";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";

export const useGetLists = (token: string | undefined, projectId: string) => {
    return useQuery({
        queryKey: ["getLists"],
        queryFn: async () => {
            const res = await axios.get(BACKEND_URL + '/project/list/' + projectId, {
                headers: {
                    'Content-Type': 'application/json',
                    Accept: 'application/json',
                    Authorization: "Bearer " + token
                },
            });
            return res.data
        },
    });
}
Saltwater CrocodileOP
Now i dont get error but it stil doesnt change the ui after the change
It just jumps back after the drag and drop
But after a refresh it shows the correct position
@Saltwater Crocodile Click to see attachment
do you see this line logged out?
console.log('UPDATED LISTS: ', values.updatedLists);
try this
 onMutate: async (values) => {
      await queryClient.cancelQueries(['getLists']);

      const prevList = queryClient.getQueryData(['getLists']);

      console.log('UPDATED LISTS: ', values.updatedLists);

      queryClient.setQueryData(['getLists'], [...values.updatedLists]);

      return { prevList };
    },
Saltwater CrocodileOP
Yes, when console logging Updated Lists it is exactly what it should be
Saltwater CrocodileOP
Still doesnt work :(
It just jumps back immediatly
@Saltwater Crocodile It just jumps back immediatly
how about remove the comment for this?
onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ['getLists'] });
    },
Saltwater CrocodileOP
Then it looks like this
But i want to bypass this delay and show it instantly
Which i thought should be working with optimistic updates
@Saltwater Crocodile Click to see attachment
use mutate(values) instead of mutateAsync(values);
Saltwater CrocodileOP
Still the same delay
I dont know what im doing wrong here
could you show the code on useMoveList
Saltwater CrocodileOP
import { BACKEND_URL } from '@/lib/constants';
import { MoveListFormData } from '@/types/project.types';
import axios from 'axios';

export const useMoveList = async (values: MoveListFormData) => {
    const { token, projectId, updatedLists, ...data } = values;
    return await axios.patch(BACKEND_URL + '/project/list/move/' + projectId, data, {
        headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json',
            Authorization: 'Bearer ' + token,
        },
    });
};
and what is updatedLists for?
Saltwater CrocodileOP
Update List is doing the position change locally, it is the exact same that happens in the Backend but i did it also in frontend to change the Object Locally so that the changes could be visible instant
@Saltwater Crocodile ts import { BACKEND_URL } from '@/lib/constants'; import { MoveListFormData } from '@/types/project.types'; import axios from 'axios'; export const useMoveList = async (values: MoveListFormData) => { const { token, projectId, updatedLists, ...data } = values; return await axios.patch(BACKEND_URL + '/project/list/move/' + projectId, data, { headers: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: 'Bearer ' + token, }, }); };
import { BACKEND_URL } from '@/lib/constants';
import { MoveListFormData } from '@/types/project.types';
import axios from 'axios';

export const useMoveList = async (values: MoveListFormData) => {
    const { token, projectId, updatedLists, ...data } = values;
    const res = await axios.patch(BACKEND_URL + '/project/list/move/' + projectId, data, {
        headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json',
            Authorization: 'Bearer ' + token,
        },
    });
    return res.data
};
try this
Saltwater CrocodileOP
Still the same, the drag and drop waits until it gets response from backend and then changes
Is it even possible to show it instant with setQueryData?
I thought so yes
it does
Saltwater CrocodileOP
But somehow it doesnt work
@Saltwater Crocodile But somehow it doesnt work
ah change this too
export const useGetLists = (token: string | undefined, projectId: string) => {
    return useQuery({
        queryKey: ["getLists"],
        queryFn: async () => {
            const res = await axios.get(BACKEND_URL + '/project/list/' + projectId, {
                headers: {
                    'Content-Type': 'application/json',
                    Accept: 'application/json',
                    Authorization: "Bearer " + token
                },
            });
            return res.data
        },
    });
}
Saltwater CrocodileOP
Stil not working
@Saltwater Crocodile Stil not working
is it on github which can share?
Saltwater CrocodileOP
ok let me have a look
@Saltwater Crocodile https://github.com/Gutiiii/projsync
which page is that?
Saltwater CrocodileOP
Board.tsx
And ProjectBoard.tsx
And page it is projects/[projectId]/board
I got Validation failed error when drag end
activeListPosition is undefined
you sure you can update the position to database?
Saltwater CrocodileOP
Yes the database gets the correct position
All of the backend stuff works
Only the instant update in frontnend fails
but your repo doesn't work for me
Saltwater CrocodileOP
Did you setup the db?
    const activeListPosition = active.data?.current?.data?.position;

    const overListPosition = over.data.current?.data?.position;

this two line
@Saltwater Crocodile Did you setup the db?
sure
don't even have position here
Saltwater CrocodileOP
Hmm thats weird
For me i get position
And all the correct values
or the code on github not update?
Saltwater CrocodileOP
Oh yes
Haha
Lemme push it
Just pished it
still get error
how can you update lol
Saltwater CrocodileOP
I dont know why you dont grt position
Did you create it normally by ui Add List?
yes
active.data.current.data doesn't event exist
Saltwater CrocodileOP
Yea i see that
Data is missing in current
Lemme check
Saltwater CrocodileOP
So normally the data should be set inside useSortable
Can you checkt that this is the same on your code and that data is correctly passed as prop to BoardColumn. Maybe with a console log data
Saltwater CrocodileOP
Can you console log the prop data
Saltwater CrocodileOP
ProjectBoard
It should pass the current list item in the lists.map
Then that should be passed as prop in data to BoardColumn
yes its there
but its not in the event of onDragEnd
Saltwater CrocodileOP
Okay thats weird normally that should be in the current.data
you sure the position get updated on your database?
Saltwater CrocodileOP
Yes that works. After refresh the positions grt displayed correct
the data only appear inside over
could you log active and over?
Saltwater CrocodileOP
I get this
I'll push my changes again, somehow some thing have been overwriten in my code
Maybe you can try to console log these values that i logged
And we can compare
Also you can consle log the list in moveList function in the project.service.ts to see, that the database mutation works
@Saltwater Crocodile Click to see attachment
@Saltwater Crocodile Also you can consle log the list in moveList function in the project.service.ts to see, that the database mutation works
can't even send the request yet because active.data.current?.data.position is undefined
Saltwater CrocodileOP
Thats really weird
@Saltwater Crocodile Thats really weird
oh i know why
I was dragging the card
and your video is dragging the list
Saltwater CrocodileOP
Oh haha, yes i didn't implement card dragging yet
Was struggling with list
So i wait with that
@Saltwater Crocodile So i wait with that
ok got it
 queryClient.setQueryData(['getLists'], values.updatedLists.sort(
        (a, b) => a.position - b.position,
      ));
Answer
Saltwater CrocodileOP
Omg thank you very much. What is the difference, why didnt it work before and why does it work wth the sort?
because you were just setting the old state
so it didn't change the position
Saltwater CrocodileOP
Oh okay, and what does a.position - b.positio exactly do?
ah nvm
It just sorts it
yes
Saltwater CrocodileOP
ohhh ofc the lists stay at the same index in the array, so they will appear in the same spot. Thank you very much
For the help
Been stuck for ages
WOuldnt it then be possible to do the sort in the lists.map from the start
Saltwater CrocodileOP
Yes it works like that.
Added the sort to the initial map
Thank you bro