# Component State

URL: https://ark-ui.com/docs/guides/component-state
LLM: https://ark-ui.com/llms.txt/guides/component-state

Learn how to manage component state using Context and Provider components.

---

Need to access a component's state? You have three options:

| Approach                        | When to use it                                |
| ------------------------------- | --------------------------------------------- |
| `Component.Context`             | Quick inline access via render props          |
| `use*Context` hooks             | Build custom child components that read state |
| `useComponent` + `RootProvider` | Control the component from outside            |

## Context Components

Use `Component.Context` to access state inline via render props. Here, `Avatar.Fallback` reads the `loaded` state to
show different content:

> **Good to know (RSC)**: The render prop pattern requires the `'use client'` directive when using React Server
> Components.

```tsx
import { Avatar } from '@ark-ui/react/avatar'
import styles from 'styles/avatar.module.css'

export const Context = () => (
  <Avatar.Root className={styles.Root}>
    <Avatar.Context>
      {(avatar) => <Avatar.Fallback className={styles.Fallback}>{avatar.loaded ? 'PA' : 'Loading'}</Avatar.Fallback>}
    </Avatar.Context>
    <Avatar.Image className={styles.Image} src="https://i.pravatar.cc/300?u=a" alt="avatar" />
  </Avatar.Root>
)
```

## Context Hooks

Every component exports a `use*Context` hook (like `useDialogContext` or `useMenuContext`). Call it from any child
component to access state and methods—no render props needed.

```tsx
import { Dialog, useDialogContext } from '@ark-ui/react/dialog'

function CustomCloseButton() {
  const dialog = useDialogContext()
  return <button onClick={() => dialog.setOpen(false)}>Close ({dialog.open ? 'open' : 'closed'})</button>
}

export const Demo = () => (
  <Dialog.Root>
    <Dialog.Trigger>Open</Dialog.Trigger>
    <Dialog.Content>
      <CustomCloseButton />
    </Dialog.Content>
  </Dialog.Root>
)
```

The hook returns the same API as `Component.Context`, just without the nesting.

## Provider Components

Need to control a component from outside its tree? Use a `useComponent` hook (like `useDialog`) with `RootProvider`.

> When you use `RootProvider`, skip the `Root` component—you don't need both.

```tsx
import { Accordion, useAccordion } from '@ark-ui/react/accordion'
import { ChevronDownIcon } from 'lucide-react'
import styles from 'styles/accordion.module.css'

export const RootProvider = () => {
  const accordion = useAccordion({
    multiple: true,
    defaultValue: ['ark-ui'],
  })

  return (
    <div className="stack">
      <output>Value: {JSON.stringify(accordion.value)}</output>

      <Accordion.RootProvider className={styles.Root} value={accordion}>
        {items.map((item) => (
          <Accordion.Item className={styles.Item} key={item.value} value={item.value}>
            <Accordion.ItemTrigger className={styles.ItemTrigger}>
              {item.title}
              <Accordion.ItemIndicator className={styles.ItemIndicator}>
                <ChevronDownIcon />
              </Accordion.ItemIndicator>
            </Accordion.ItemTrigger>
            <Accordion.ItemContent className={styles.ItemContent}>
              <div className={styles.ItemBody}>{item.content}</div>
            </Accordion.ItemContent>
          </Accordion.Item>
        ))}
      </Accordion.RootProvider>
    </div>
  )
}

const items = [
  {
    value: 'ark-ui',
    title: 'What is Ark UI?',
    content: 'A headless component library for building accessible web apps.',
  },
  {
    value: 'getting-started',
    title: 'How to get started?',
    content: 'Install the package and import the components you need.',
  },
  {
    value: 'maintainers',
    title: 'Who maintains this project?',
    content: 'Ark UI is maintained by the Chakra UI team.',
  },
]
```

## Choosing the Right Approach

- **`Component.Context`** — Quick inline access for conditional rendering
- **`use*Context` hooks** — Build reusable child components that need parent state
- **`useComponent` + `RootProvider`** — Trigger actions from outside (like opening a dialog from a menu item)