diff --git a/front/components/assistant/conversation/input_bar/InputBar.tsx b/front/components/assistant/conversation/input_bar/InputBar.tsx index 1b458b9a9fbd..fa6f5332f2e0 100644 --- a/front/components/assistant/conversation/input_bar/InputBar.tsx +++ b/front/components/assistant/conversation/input_bar/InputBar.tsx @@ -5,8 +5,10 @@ import { AgentMention, MentionType } from "@dust-tt/types"; import { createContext, Fragment, + useCallback, useContext, useEffect, + useRef, useState, } from "react"; import { mutate } from "swr"; @@ -40,7 +42,31 @@ function AgentMention({ ); } -// AGENT LIST +// Custom hook to synchronize state with a ref as a temporary workaround. +// This hack is used to maintain a synchronous and up-to-date reference to state values +// that are otherwise affected by parent component re-renders due to changing dependencies. +// This approach ensures that the latest state is accessible synchronously when needed +// for operations that cannot rely on the normal asynchronous nature of setState. +// This is not an ideal solution and should be addressed with a more robust state management strategy +// as a follow-up action to minimize unnecessary re-renders and improve component performance. +function useSyncedState(initialValue: T | undefined) { + const [state, setState] = useState(initialValue); + const ref = useRef(initialValue); + + // Synchronize ref with state + useEffect(() => { + ref.current = state; + }, [state]); + + // Function to update both state and ref + const setSyncedState = useCallback((newValue: T | undefined) => { + setState(newValue); + ref.current = newValue; // This line isn't strictly necessary because of the useEffect above + }, []); + + // Return both state and ref, along with the setter function + return [state, ref, setSyncedState] as const; +} export function AssistantInputBar({ owner, @@ -57,12 +83,14 @@ export function AssistantInputBar({ conversationId: string | null; stickyMentions?: AgentMention[]; }) { - const [contentFragmentBody, setContentFragmentBody] = useState< - string | undefined - >(undefined); - const [contentFragmentFilename, setContentFragmentFilename] = useState< - string | undefined - >(undefined); + const [contentFragmentBody, contentFragmentBodyRef, setContentFragmentBody] = + useSyncedState(undefined); + const [ + contentFragmentFilename, + contentFragmentFilenameRef, + setContentFragmentFilename, + ] = useSyncedState(undefined); + const { agentConfigurations } = useAgentConfigurations({ workspaceId: owner.sId, agentsGetView: conversationId ? { conversationId } : "list", @@ -103,10 +131,10 @@ export function AssistantInputBar({ contentType: string; } | undefined = undefined; - if (contentFragmentBody && contentFragmentFilename) { + if (contentFragmentFilenameRef.current && contentFragmentBodyRef.current) { contentFragment = { - title: contentFragmentFilename, - content: contentFragmentBody, + title: contentFragmentFilenameRef.current, + content: contentFragmentBodyRef.current, url: null, contentType: "file_attachment", };