# Component State

URL: https://ark-ui.com/docs/guides/component-state
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/guides/component-state.mdx

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

---

## Context Components

Context components expose state and functions to child components. In this example, `Avatar.Fallback` renders based on
`loaded` state.

**Example: context**

#### React

```tsx
import { Avatar } from '@ark-ui/react/avatar'

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

```

#### Solid

```tsx
import { Avatar } from '@ark-ui/solid/avatar'

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

```

#### Vue

```vue
<script setup lang="ts">
import { Avatar } from '@ark-ui/vue/avatar'
</script>

<template>
  <Avatar.Root>
    <Avatar.Context v-slot="avatar">
      <Avatar.Fallback>
        {{ avatar.loaded ? 'PA' : 'Loading' }}
      </Avatar.Fallback>
    </Avatar.Context>
    <Avatar.Image src="https://i.pravatar.cc/300" alt="avatar" />
  </Avatar.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Avatar } from '@ark-ui/svelte/avatar'
</script>

<Avatar.Root>
  <Avatar.Context>
    {#snippet api(avatar)}
      <Avatar.Fallback>
        {#if avatar().loaded}
          <p>PA</p>
        {:else}
          <p>Loading</p>
        {/if}
      </Avatar.Fallback>
    {/snippet}
  </Avatar.Context>
  <Avatar.Image src="https://i.pravatar.cc/3000?u=b" alt="avatar" />
</Avatar.Root>

```

> **Good to know (RSC)**: Due to the usage of render prop, you might need to add the `'use client'` directive at the top
> of your file when using React Server Components.

## Provider Components

Provider components can help coordinate state and behavior between multiple components, enabling interactions that
aren't possible with `Context` components alone. They are used alongside component hooks.

**Example: root-provider**

#### React

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

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

  return (
    <>
      <button onClick={() => accordion.setValue(['Vue'])}>Set to Vue</button>

      <Accordion.RootProvider value={accordion}>
        {['React', 'Solid', 'Vue', 'Svelte'].map((item) => (
          <Accordion.Item key={item} value={item}>
            <Accordion.ItemTrigger>
              What is {item}?
              <Accordion.ItemIndicator>
                <ChevronDownIcon />
              </Accordion.ItemIndicator>
            </Accordion.ItemTrigger>
            <Accordion.ItemContent>{item} is a JavaScript library for building user interfaces.</Accordion.ItemContent>
          </Accordion.Item>
        ))}
      </Accordion.RootProvider>
    </>
  )
}

```

#### Solid

```tsx
import { Accordion, useAccordion } from '@ark-ui/solid/accordion'
import { ChevronDownIcon } from 'lucide-solid'
import { Index } from 'solid-js'

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

  return (
    <>
      <button onClick={() => accordion().setValue(['Vue'])}>Set to Vue</button>

      <Accordion.RootProvider value={accordion}>
        <Index each={['React', 'Solid', 'Vue', 'Svelte']}>
          {(item) => (
            <Accordion.Item value={item()}>
              <Accordion.ItemTrigger>
                What is {item()}?
                <Accordion.ItemIndicator>
                  <ChevronDownIcon />
                </Accordion.ItemIndicator>
              </Accordion.ItemTrigger>
              <Accordion.ItemContent>
                {item()} is a JavaScript library for building user interfaces.
              </Accordion.ItemContent>
            </Accordion.Item>
          )}
        </Index>
      </Accordion.RootProvider>
    </>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { Accordion, useAccordion } from '@ark-ui/vue/accordion'
import { ChevronRightIcon } from 'lucide-vue-next'

const items = ['React', 'Solid', 'Vue', 'Svelte']

const accordion = useAccordion({
  multiple: true,
  defaultValue: ['React'],
})
</script>

<template>
  <button @click="accordion.setValue(['Vue'])">Set to Vue</button>

  <Accordion.RootProvider :value="accordion">
    <Accordion.Item v-for="item in items" :key="item" :value="item">
      <Accordion.ItemTrigger>
        What is {{ item }}?
        <Accordion.ItemIndicator>
          <ChevronRightIcon />
        </Accordion.ItemIndicator>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>{{ item }} is a JavaScript library for building user interfaces.</Accordion.ItemContent>
    </Accordion.Item>
  </Accordion.RootProvider>
</template>

```

#### Svelte

```svelte
<script>
  import { Accordion, useAccordion } from '@ark-ui/svelte/accordion'
  import { ChevronDownIcon } from 'lucide-svelte'

  const id = $props.id()
  const accordion = useAccordion({
    id,
    defaultValue: ['React'],
  })
</script>

<div>
  <div>Open items: {JSON.stringify(accordion().value)}</div>
  <Accordion.RootProvider value={accordion}>
    {#each ['React', 'Solid', 'Vue', 'Svelte'] as item (item)}
      <Accordion.Item value={item}>
        <Accordion.ItemTrigger>
          What is {item}?
          <Accordion.ItemIndicator>
            <ChevronDownIcon />
          </Accordion.ItemIndicator>
        </Accordion.ItemTrigger>
        <Accordion.ItemContent>
          {item} is a JavaScript library for building user interfaces.
        </Accordion.ItemContent>
      </Accordion.Item>
    {/each}
  </Accordion.RootProvider>
</div>

```

> When using the `RootProvider` component, you don't need to use the `Root` component.

See more in [Examples](/examples/popover-selection).