diff --git a/.changeset/metal-pumas-repeat.md b/.changeset/metal-pumas-repeat.md new file mode 100644 index 00000000000..56c8c25a037 --- /dev/null +++ b/.changeset/metal-pumas-repeat.md @@ -0,0 +1,5 @@ +--- +"@aws-amplify/ui-react-ai": patch +--- + +fix(ai): no more unnecessary re-renders in AIConversation diff --git a/packages/react-ai/src/components/AIConversation/AIConversation.tsx b/packages/react-ai/src/components/AIConversation/AIConversation.tsx index 200dd604c62..248814a8e9f 100644 --- a/packages/react-ai/src/components/AIConversation/AIConversation.tsx +++ b/packages/react-ai/src/components/AIConversation/AIConversation.tsx @@ -13,7 +13,7 @@ import { Form } from './views/default/Form'; import { PromptList } from './views/default/PromptList'; import { AutoHidablePromptControl } from './views/Controls'; import { ComponentClassName } from '@aws-amplify/ui'; -import createProvider from './createProvider'; +import { AIConversationProvider } from './AIConversationProvider'; interface AIConversationBaseProps extends AIConversationProps, @@ -44,7 +44,14 @@ function AIConversationBase({ }, }; - const Provider = createProvider({ + const providerProps = { + messages, + handleSendMessage, + avatars: { + ...defaultAvatars, + ...avatars, + }, + isLoading, elements: { Text: React.forwardRef( function _Text(props, ref) { @@ -64,20 +71,10 @@ function AIConversationBase({ }, displayText, allowAttachments, - }); - - const providerProps = { - messages, - handleSendMessage, - avatars: { - ...defaultAvatars, - ...avatars, - }, - isLoading, }; return ( - + @@ -85,7 +82,7 @@ function AIConversationBase({ - + ); } diff --git a/packages/react-ai/src/components/AIConversation/AIConversationProvider.tsx b/packages/react-ai/src/components/AIConversation/AIConversationProvider.tsx new file mode 100644 index 00000000000..84b02cb0768 --- /dev/null +++ b/packages/react-ai/src/components/AIConversation/AIConversationProvider.tsx @@ -0,0 +1,78 @@ +import React from 'react'; + +import { ElementsProvider } from '@aws-amplify/ui-react-core/elements'; + +import { AIConversationInput, AIConversationProps } from './types'; +import { defaultAIConversationDisplayTextEn } from './displayText'; +import { + ConversationDisplayTextProvider, + SuggestedPromptProvider, + ConversationInputContextProvider, + AvatarsProvider, + ActionsProvider, + MessageVariantProvider, + MessagesProvider, + ControlsProvider, + LoadingContextProvider, + ResponseComponentsProvider, + SendMessageContextProvider, +} from './context'; +import { AttachmentProvider } from './context/AttachmentContext'; + +interface AIConversationProviderProps + extends AIConversationInput, + AIConversationProps { + children?: React.ReactNode; +} + +export const AIConversationProvider = ({ + elements, + actions, + suggestedPrompts, + responseComponents, + variant, + controls, + displayText, + allowAttachments, + messages, + handleSendMessage, + avatars, + isLoading, + children, +}: AIConversationProviderProps): React.JSX.Element => { + const _displayText = { + ...defaultAIConversationDisplayTextEn, + ...displayText, + }; + return ( + + + + + + + + + + + + + + {children} + + + + + + + + + + + + + + ); +}; diff --git a/packages/react-ai/src/components/AIConversation/createAIConversation.tsx b/packages/react-ai/src/components/AIConversation/createAIConversation.tsx index f894133611a..83bad22362f 100644 --- a/packages/react-ai/src/components/AIConversation/createAIConversation.tsx +++ b/packages/react-ai/src/components/AIConversation/createAIConversation.tsx @@ -14,7 +14,7 @@ import { MessagesControl, PromptControl, } from './views'; -import createProvider from './createProvider'; +import { AIConversationProvider } from './AIConversationProvider'; /** * @experimental @@ -33,28 +33,26 @@ export function createAIConversation(input: AIConversationInput = {}): { allowAttachments, } = input; - const Provider = createProvider({ - elements, - actions, - suggestedPrompts, - responseComponents, - variant, - controls, - displayText, - allowAttachments, - }); - function AIConversation(props: AIConversationProps): JSX.Element { const { messages, avatars, handleSendMessage, isLoading } = props; + const providerProps = { + elements, + actions, + suggestedPrompts, + responseComponents, + variant, + controls, + displayText, + allowAttachments, + messages, + avatars, + handleSendMessage, + isLoading, + }; return ( - + - + ); } @@ -67,7 +65,7 @@ export function createAIConversation(input: AIConversationInput = {}): { SuggestedPrompts: PromptControl, }; - AIConversation.Provider = Provider; + AIConversation.Provider = AIConversationProvider; AIConversation.Conversation = Conversation; AIConversation.Controls = Controls; diff --git a/packages/react-ai/src/components/AIConversation/createProvider.tsx b/packages/react-ai/src/components/AIConversation/createProvider.tsx deleted file mode 100644 index 0d0f841eb87..00000000000 --- a/packages/react-ai/src/components/AIConversation/createProvider.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; - -import { ElementsProvider } from '@aws-amplify/ui-react-core/elements'; - -import { AIConversationInput, AIConversationProps } from './types'; -import { defaultAIConversationDisplayTextEn } from './displayText'; -import { - ConversationDisplayTextProvider, - SuggestedPromptProvider, - ConversationInputContextProvider, - AvatarsProvider, - ActionsProvider, - MessageVariantProvider, - MessagesProvider, - ControlsProvider, - LoadingContextProvider, - ResponseComponentsProvider, - SendMessageContextProvider, -} from './context'; -import { AttachmentProvider } from './context/AttachmentContext'; - -export default function createProvider({ - elements, - actions, - suggestedPrompts, - responseComponents, - variant, - controls, - displayText, - allowAttachments, -}: Pick< - AIConversationInput, - | 'elements' - | 'actions' - | 'suggestedPrompts' - | 'responseComponents' - | 'variant' - | 'controls' - | 'displayText' - | 'allowAttachments' ->) { - return function Provider({ - children, - messages, - avatars, - handleSendMessage, - isLoading, - }: { - children?: React.ReactNode; - } & Pick< - AIConversationProps, - 'messages' | 'avatars' | 'handleSendMessage' | 'isLoading' - >): React.JSX.Element { - const _displayText = { - ...defaultAIConversationDisplayTextEn, - ...displayText, - }; - return ( - - - - - - - - - - - - - - {children} - - - - - - - - - - - - - - ); - }; -}