T
TanStack2y ago
ratty-blush

Using react query to distribute state when using with web sockets

If it is not advised to use react query to distribute some state in app, why connecting query with websocket is a suggested pattern. References: 1. https://tkdodo.eu/blog/practical-react-query#dont-use-the-querycache-as-a-local-state-manager 2. https://tkdodo.eu/blog/using-web-sockets-with-react-query#partial-data-updates 3.https://tanstack.com/query/latest/docs/react/reference/QueryClient#queryclientsetquerydata I was hoping i could do something like below to keep my multiple chat(1) floating windows in sync doing something along these lines:
export const useChat: void = () => {
const queryClient = useQueryClient();
const { lastJsonMessage } = useWebSocket<ChatEventType>(SocketGateways.userChat, webSocketOptions);


useEffect(() => {
if (!lastJsonMessage) return;
const { userId } = lastJsonMessage;
if (!userId) return;
queryClient.setQueryData<IChatListItem[] | undefined>(
[chatQuerykeys.chatList()],
(currentChatList) => chatListReducer(currentChatList, lastJsonMessage)
);

queryClient.setQueryData<IChatConversation | undefined>(
[chatQuerykeys.conversation(userId)],
(currentConversation) => conversationReducer(currentConversation, lastJsonMessage)
);

queryClient.setQueryData<IChatMessage[] | undefined>(
[chatQuerykeys.messages(userId)],
(currentMessages) => messagesReducer(currentMessages, lastJsonMessage)
);
}, [queryClient, lastJsonMessage]);

};

export const useMessages = (userId: string) => {
return useQuery({
queryKey: chatQuerykeys.messages(userId),
queryFn: () => chatAPI.getMessages(userId),
staleTime: Infinity,
keepPreviousData: true,
refetchOnMount: false,
retry: false
});
};

The reducers have these signatures eg.
const messagesReducer = (
currentMessages: IChatMessage[] | undefined,
event: ChatEventType
): IChatMessage[] => {
//reducer logic to return new messages state
}
export const useChat: void = () => {
const queryClient = useQueryClient();
const { lastJsonMessage } = useWebSocket<ChatEventType>(SocketGateways.userChat, webSocketOptions);


useEffect(() => {
if (!lastJsonMessage) return;
const { userId } = lastJsonMessage;
if (!userId) return;
queryClient.setQueryData<IChatListItem[] | undefined>(
[chatQuerykeys.chatList()],
(currentChatList) => chatListReducer(currentChatList, lastJsonMessage)
);

queryClient.setQueryData<IChatConversation | undefined>(
[chatQuerykeys.conversation(userId)],
(currentConversation) => conversationReducer(currentConversation, lastJsonMessage)
);

queryClient.setQueryData<IChatMessage[] | undefined>(
[chatQuerykeys.messages(userId)],
(currentMessages) => messagesReducer(currentMessages, lastJsonMessage)
);
}, [queryClient, lastJsonMessage]);

};

export const useMessages = (userId: string) => {
return useQuery({
queryKey: chatQuerykeys.messages(userId),
queryFn: () => chatAPI.getMessages(userId),
staleTime: Infinity,
keepPreviousData: true,
refetchOnMount: false,
retry: false
});
};

The reducers have these signatures eg.
const messagesReducer = (
currentMessages: IChatMessage[] | undefined,
event: ChatEventType
): IChatMessage[] => {
//reducer logic to return new messages state
}
QueryClient | TanStack Query Docs
QueryClient The QueryClient can be used to interact with a cache:
Practical React Query
Let me share with you the experiences I have made lately with React Query. Fetching data in React has never been this delightful...
Using WebSockets with React Query
A step-by-step guide on how to make real-time notifications work with react-query
0 Replies
No replies yetBe the first to reply to this messageJoin

Did you find this page helpful?