Introduction to C1 State

When C1 generates a live UI, it doesn’t just render static components. It also tracks the values inside those components—things like form inputs, toggles, or selections. This is called C1 State. Why it matters C1 State makes interactive flows possible:
  • Form fields can hold values until the user submits them.
  • Inputs, dropdowns, or toggles can remember a user’s selection.
  • State can be persisted and when user reloads the chat from history, the components will be restored to the state they were in when the user last interacted with them.
Without C1 State, every refresh would reset the UI from scratch.

Automatic State Management

For all built-in C1 components, such as forms, text inputs, and toggles, state is managed for you automatically by the C1 SDK. You do not need to write your own useState or onChange handlers to track the values of these components. When a user types into a C1-generated input, its value is tracked internally, providing a seamless “it just works” experience out of the box.

Persisting State Across Sessions

By default, C1 State is stored in the browser’s memory and will be lost if the user refreshes the page. To create a persistent experience, you can save the state to your database whenever it changes. The <C1Component> provides the updateMessage callback prop for this purpose. This function is called every time a state value changes within the UI, providing you with a complete snapshot of the C1 DSL that includes the latest state. You can then save this updated DSL string to your database.
<C1Component
  c1Response={initialC1Response}
  updateMessage={(updatedC1Response) => {
    // `updatedC1Response` is the full C1 DSL string with the latest state merged in.
    // Save this string to your database to persist the UI's current state.
    saveToDatabase({
      content: updatedC1Response,
    });
  }}
/>
The updateMessage callback provides the complete C1 DSL with state already merged. You only need to store this single string, not the state and the original DSL separately.

State in Custom Components

When building your own interactive components, you can integrate them into C1’s state system using the useC1State hook. This hook works similarly to React’s useState but ensures that your component’s state is tracked and managed by C1. It takes a unique key as its argument, which is used to identify and store the state value within the C1 DSL.
import { useC1State } from '@thesysai/genui-sdk';

// A custom toggle component
function CustomToggle() {
  // 'toggle-enabled' is the unique key for this state value
  const [value, setValue] = useC1State('toggle-enabled');

  return (
    <button onClick={() => setValue(!value)}>
      {value ? 'On' : 'Off'}
    </button>
  );
}
By using this hook, your custom components will behave just like native C1 components, with their state being automatically tracked, persisted, and available in actions. For more details, see the complete Custom Components guide.