> ## Documentation Index
> Fetch the complete documentation index at: https://sunpeak.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# useAppState

> UI state synced to the host and made visible to the model.

<Badge color="yellow">sunpeak API</Badge>

## Overview

Manages UI state that is automatically synced to the host via [`updateModelContext`](/docs/mcp-apps/app/requests/update-model-context). Works like React's `useState`, but each update is pushed to the host so the AI model can see it on the next message. Use this for user decisions, selections, or any state the model should be aware of.

The hook starts from `defaultState` whenever the View mounts. It does not restore state after the host recreates the iframe. For durable data, save and reload it through server tools. See [MCP App State Persistence](/docs/mcp-apps/state-persistence).

Use an object-shaped state value. The hook sends it as `updateModelContext().structuredContent`, which the MCP Apps protocol defines as an object.

<Card horizontal title="Wraps updateModelContext" icon="cube" href="/docs/mcp-apps/app/requests/update-model-context">
  MCP Apps SDK reference
</Card>

## Import

```tsx theme={null}
import { useAppState } from 'sunpeak';
```

## Signature

```tsx theme={null}
function useAppState<T>(
  defaultState: T
): readonly [T, (state: SetStateAction<T>) => void]
```

## Parameters

<ResponseField name="defaultState" type="T" required>
  Initial state value.
</ResponseField>

## Returns

<ResponseField name="return" type="[T, (state: SetStateAction<T>) => void]">
  A tuple containing the current state and a setter function, similar to React's `useState`.
</ResponseField>

## Usage

```tsx theme={null}
import { useAppState } from 'sunpeak';

interface ReviewState {
  decision: 'approved' | 'rejected' | null;
  decidedAt: string | null;
}

function ReviewResource() {
  const [state, setState] = useAppState<ReviewState>({
    decision: null,
    decidedAt: null,
  });

  const handleApprove = () => {
    setState({ decision: 'approved', decidedAt: new Date().toISOString() });
  };

  return (
    <div>
      <p>Decision: {state.decision ?? 'Pending'}</p>
      <button onClick={handleApprove}>Approve</button>
    </div>
  );
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.