From a76ec7ae1df42eb32d8fd009a2cfd73f5dfbc6db Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Sun, 21 Sep 2025 22:36:30 -0400 Subject: [PATCH] fix: immutable optimistic update to trigger re-render --- layouts/LayoutDefault.tsx | 18 +++++++++++++----- pages/chat/@id/+Page.tsx | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/layouts/LayoutDefault.tsx b/layouts/LayoutDefault.tsx index 6850bc3..6364873 100644 --- a/layouts/LayoutDefault.tsx +++ b/layouts/LayoutDefault.tsx @@ -68,9 +68,18 @@ function getQueryClient() { // suspends during the initial render. This may not be needed if we // have a suspense boundary BELOW the creation of the query client if (!browserQueryClient) browserQueryClient = makeQueryClient(); + // This code is for all users + window.__TANSTACK_QUERY_CLIENT__ = browserQueryClient; return browserQueryClient; } +// This code is only for TypeScript +declare global { + interface Window { + __TANSTACK_QUERY_CLIENT__: import("@tanstack/query-core").QueryClient; + } +} + export function SignInWithGoogle() { const pageContext = usePageContext(); /** This is populated using the +onCreatePageContext.server.ts hook */ @@ -232,7 +241,9 @@ function NavLinkChat() { const { urlPathname } = pageContext; const trpc = useTRPC(); const queryClient = useQueryClient(); - // const + const { data: conversations } = useQuery( + trpc.chat.conversations.fetchAll.queryOptions() + ); const startConversation = useMutation( trpc.chat.conversations.start.mutationOptions({ onSuccess: () => { @@ -286,9 +297,6 @@ function NavLinkChat() { }) ); - const { data: conversations } = useQuery( - trpc.chat.conversations.fetchAll.queryOptions() - ); // const selectedConversationId = useStore( // (state) => state.selectedConversationId // ); @@ -356,7 +364,7 @@ function NavLinkChat() { > {conversations?.map((conversation) => ( = [ - ...previousConversations, - { - ...conversation, - title, - } as Conversation, - ]; + + /** MUST make a deep, immutable copy in order to trigger re-render of + * oberserving components. */ + const newConversations: Array = JSON.parse( + JSON.stringify(previousConversations) + ); + const conversationToUpdate = newConversations.find((c) => c.id === id); + if (!conversationToUpdate) { + return { previousConversations, newConversations }; + } + conversationToUpdate.title = title; queryClient.setQueryData>( trpc.chat.conversations.fetchAll.queryKey(), newConversations @@ -508,10 +512,6 @@ export default function ChatPage() { onKeyUp={(e) => { if (e.key === "Enter") { e.preventDefault(); - // updateConversationTitle.mutateAsync({ - // id: conversationId, - // title: e.currentTarget.value, - // }); e.currentTarget.blur(); } }}