Loading...

Component State

Pass component state to Tambo as context for following user messages.

Components generated by Tambo may have internal state values that are updated by user interactions after the component is rendered. To allow Tambo to track the current value of a component's internal state, replace useState with useTamboComponentState.

This allows Tambo to consider the current state values when responding to subsequent user messages, and allows rendering previous thread messages with their latest values.

Demo GIF

Tracking State with useTamboComponentState

Consider this simple React component that allows a user to update an emailBody field, and tracks whether the email has been sent:

Simple email component

export const EmailSender = () => {
  ...
  const [emailBody, setEmailBody] = useState("") // tracks the message being typed
  const [isSent, setIsSent] = useState(false) // tracks whether the 'send' button has been clicked
  ...
}

If Tambo renders this component and the user edits the emailBody field, Tambo will not know about the edit. A following user message like "Help me edit what I've typed so far" will not generate a relevant response.

To allow Tambo to see these state values, simply replace useState with useTamboComponentState, and pass a keyName for each value:

Email component with tambo state
import { useTamboComponentState } from "@tambo-ai/react";

export const EmailSender = () => {
  ...
  const [emailBody, setEmailBody] = useTamboComponentState("emailBody", "");
  const [isSent, setIsSent] = useTamboComponentState("isSent", false);
  ...
}

Now tambo will know the current values of emailBody and isSent.

Updating editable state from props

Often when we have an editable state value, like the emailBody above, we want Tambo to be able to generate and stream in the initial value. If a user sends "Help me generate an email asking about a good time to meet," Tambo should be able to fill in the value with relevant text, and then the user should be able to edit it.

When using useState this can be done by adding a useEffect that updates the state value with prop value changes:

Simple email component

export const EmailSender = ({ initialEmailBody }: { initialEmailBody: string }) => {
  ...
  const [emailBody, setEmailBody] = useState("") // tracks the message being typed
  const [isSent, setIsSent] = useState(false) // tracks whether the 'send' button has been clicked

  useEffect(() => {
    setEmailBody(initialEmailBody)
  }, [initialEmailBody])
  ...
}

However, when using useTamboComponentState, this pattern will cause the initial prop value to overwrite the latest stored state value when re-rendering a previously generated component.

Instead, use the setFromProp parameter of useTamboComponentState to specify a prop value that should be used to set the initial state value:

Simple email component

export const EmailSender = ({ initialEmailBody }: { initialEmailBody: string }) => {
  ...
  const [emailBody, setEmailBody] = useTamboComponentState("emailBody", "", initialEmailBody) // tracks the message being typed, and sets initial value from the prop
  const [isSent, setIsSent] = useTamboComponentState("isSent", false) // tracks whether the 'send' button has been clicked
  ...
}