Created
May 14, 2024 15:53
-
-
Save Slyracoon23/b1b3f5225ad56e2a84d00e2efd2b3c64 to your computer and use it in GitHub Desktop.
Bug: Thread details not updating correctly in Context Provider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client" | |
// contexts/MainContext.tsx | |
import React, { createContext, use, useContext, useEffect, useState } from "react" | |
import { useParams, usePathname, useSearchParams } from "next/navigation" | |
import { useThreadDetail } from "@/lib_v2/frontend/provider/hooks/use-thread-detail" | |
import { useThreads } from "@/lib_v2/frontend/provider/hooks/use-threads" | |
import { useAiAction } from "../hooks/use-ai-action" | |
import { useThreadActions } from "../hooks/use-thread-ai-action" | |
import { useThreadMessages } from "../hooks/use-thread-messages" | |
import { useOrgActions } from "../hooks/use-workspace-ai-action" | |
import { fetchThreadDetails } from "../services/thread-detail" | |
interface MainContextState { | |
threads: { | |
threads: any | |
threadsIsLoading: boolean | |
threadsError: any | |
} | |
threadMessages: { | |
threadMessages: any | |
threadMessagesIsLoading: boolean | |
threadMessagesError: any | |
} | |
threadDetail: { | |
threadDetails: any | |
threadDetailsIsLoading: boolean | |
threadDetailsError: any | |
} | |
orgActions: { | |
orgActions: any | |
orgActionsIsLoading: boolean | |
orgActionsError: string | null | |
} | |
threadActions: { | |
threadActions: any | |
threadActionsIsLoading: boolean | |
threadActionsError: string | null | |
} | |
actionData: { | |
actionData: any | |
actionDataIsLoading: boolean | |
actionDataError: string | null | |
} | |
error: Error | null | |
setError: React.Dispatch<React.SetStateAction<Error | null>> | |
} | |
const MainContext = createContext<MainContextState | undefined>(undefined) | |
const extractIdFromUrl = (pathname: string | null) => { | |
if (!pathname) return null | |
const paths = pathname.split("/").filter(Boolean) | |
if (paths.includes("thread")) { | |
// URL contains thread ID | |
const threadIndex = paths.indexOf("thread") | |
return paths[threadIndex + 1] | |
} else if (paths.includes("task")) { | |
// URL contains action ID | |
const actionIndex = paths.indexOf("task") | |
return paths[actionIndex + 1] | |
} | |
return null | |
} | |
export const MainProvider: React.FC<{ children: React.ReactNode }> = ({ | |
children, | |
}) => { | |
const [error, setError] = useState<Error | null>(null) | |
const pathname = usePathname() | |
const searchParams = useSearchParams() | |
// Extract org_id from the pathname | |
const paths = pathname?.split("/").filter(Boolean) || [] | |
const org_id = paths[1] | |
// Extract thread_id or action_id from the pathname | |
const id = extractIdFromUrl(pathname) | |
const actionId = extractIdFromUrl(pathname) | |
const { threadDetails, threadDetailsError, threadDetailsIsLoading } = | |
useThreadDetail(id as string) | |
const { threads, threadsError, threadsIsLoading } = useThreads( | |
org_id as string | |
) | |
const { orgActions, orgActionsIsLoading, orgActionsError } = useOrgActions( | |
org_id as string | |
) | |
const { threadActions, threadActionsIsLoading, threadActionsError } = | |
useThreadActions(id as string, org_id as string) | |
const { threadMessages, threadMessagesError, threadMessagesIsLoading } = | |
useThreadMessages(org_id as string, id as string) | |
const { actionData, actionDataIsLoading, actionDataError } = useAiAction( | |
actionId as string, | |
org_id as string | |
) | |
// Log threadDetails state whenever it is updated | |
useEffect(() => { | |
console.log("threadDetails updated in MainProvider:", threadDetails) | |
}, [threadDetails]) | |
useEffect(() => { | |
console.log("threads updated in MainProvider:", threads) | |
}, [threads]) | |
const value = { | |
threads: { | |
threads, | |
threadsIsLoading, | |
threadsError, | |
}, | |
threadMessages: { | |
threadMessages, | |
threadMessagesError, | |
threadMessagesIsLoading, | |
}, | |
threadDetail: { | |
threadDetails, | |
threadDetailsError, | |
threadDetailsIsLoading, | |
}, | |
orgActions: { | |
orgActions, | |
orgActionsIsLoading, | |
orgActionsError, | |
}, | |
threadActions: { | |
threadActions, | |
threadActionsIsLoading, | |
threadActionsError, | |
}, | |
actionData: { | |
actionData, | |
actionDataIsLoading, | |
actionDataError, | |
}, | |
error, | |
setError, | |
} | |
return <MainContext.Provider value={value}>{children}</MainContext.Provider> | |
} | |
export const useMain = () => { | |
const context = useContext(MainContext) | |
if (!context) { | |
throw new Error("useMain must be used within a MainProvider") | |
} | |
return context | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from "react" | |
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs" | |
import { useMutation } from "@tanstack/react-query" | |
import { set } from "date-fns" | |
import { usePathname } from "next/navigation" | |
interface UpdateParams { | |
threadId: string | |
newStatus?: string | |
newPriority?: string | |
newAssignee?: string | |
userId: string | |
orgId: number | |
} | |
interface ThreadDetails { | |
id: string // Add id field | |
source_thread_id: string | |
status?: string // Add status field | |
// Add other properties of the thread details object | |
} | |
const supabase = createClientComponentClient() | |
export const useThreadDetail = (threadId: string) => { | |
const [threadDetails, setThreadDetails] = useState<ThreadDetails | null>(null) | |
const [isLoading, setIsLoading] = useState(false) | |
const [error, setError] = useState<string | null>(null) | |
const pathname = usePathname() | |
// Extract org_id from the pathname | |
const paths = pathname?.split("/").filter(Boolean) || [] | |
const orgId = paths[1] | |
useEffect(() => { | |
console.log("threadDetails updated in Hook:", threadDetails) | |
}, [threadDetails]) | |
// const updateMetadata = async (params: UpdateParams) => { | |
// try { | |
// const response = await fetch( | |
// `/api/v2/orgs/${orgId}/threads/metadata/${threadId}`, | |
// { | |
// method: "PUT", | |
// headers: { | |
// "Content-Type": "application/json", | |
// }, | |
// body: JSON.stringify(params), | |
// } | |
// ); | |
// if (!response.ok) { | |
// throw new Error("Failed to update thread metadata"); | |
// } | |
// const data = await response.json(); | |
// return data; | |
// } catch (error) { | |
// console.error("Failed to update thread metadata:", error); | |
// throw error; | |
// } | |
// }; | |
// const { mutate: updateThreadMetadata } = useMutation({ | |
// mutationFn: updateMetadata, | |
// }); | |
const fetchThreadDetails = async () => { | |
try { | |
setIsLoading(true) | |
const response = await fetch( | |
`/api/v2/orgs/${orgId}/threads/metadata/${threadId}` | |
) | |
if (!response.ok) { | |
throw new Error("Failed to fetch thread") | |
} | |
const data = await response.json() | |
console.log("setting thread details", data) | |
// debugger; | |
setThreadDetails(data) | |
} catch (error) { | |
console.error("Failed to fetch thread:", error) | |
setError(error.message) | |
} finally { | |
setIsLoading(false) | |
} | |
} | |
useEffect(() => { | |
console.log("fetching thread details", threadDetails) | |
fetchThreadDetails() | |
}, [threadId]) | |
useEffect(() => { | |
const channel = supabase | |
.channel(`thread_metadata:id=eq.${threadId}:update`) | |
.on( | |
"postgres_changes", | |
{ | |
event: "UPDATE", | |
schema: "public", | |
table: "thread_metadata", | |
filter: `id=eq.${threadId}`, | |
}, | |
(payload) => { | |
console.log("thread metadata update", payload) | |
// debugger; | |
// const new_data = { | |
// id: payload.new.id, | |
// source_thread_id: payload.new.source_thread_id, | |
// status: payload.new.status, | |
// } | |
setThreadDetails(payload.new) | |
// debugger; | |
// fetchThreadDetails(); | |
} | |
) | |
.subscribe() | |
return () => { | |
supabase.removeChannel(channel) | |
} | |
}, [threadId]) | |
return { | |
threadDetails, | |
threadDetailsError: error, | |
threadDetailsIsLoading: isLoading, | |
// updateThreadMetadata, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i think To ensure that the Context Provider correctly re-renders when the data fetched by the custom hook updates, regardless of the number of arguments passed to the hook, we need to ensure the custom hook correctly handles multiple arguments and that the Context Provider correctly consumes this data.
Steps to Diagnose and Resolve the Issue
Ensure Dependencies Are Correctly Managed in the Custom Hook:
Make sure the dependencies in the custom hook are properly defined so that the hook re-fetches the data when any of the arguments change.
Verify the Context Provider Uses the Updated Data Correctly:
Ensure that the Context Provider is correctly using the data from the custom hook and re-renders when the data changes.
Refactor the Custom Hook:
Refactor the custom hook to use multiple arguments and ensure it correctly updates the data.
Here’s the updated MainProvider to use the custom hook with multiple arguments: