DocsBlog
  • 1.1.2

  • light

    dark

    system

    Switch mode
  • Cerberus

    Acheron

    Elysium

Get Started
Components
Data Grid
Signals
Styling
Theming

Get Started

OverviewReactivityData FetchingStores

Primitives

createSignalcreateQuerycreateMutationcreateComputedcreateEffectcreateStoreContextbatch

Hooks

useQueryuseMutationuseReaduseSignal

Components

ReactiveText

On this page

  • Edit this page on Github

Contextual Signal Stores

Learn how to create Context-based signal stores in React.

  • source
import { createStoreContext } from '@cerberus/signals'

Introduction

With Cerberus Signals, you can create global (signal-based) stores that manage data and actions in a single place. Sometimes, you may want this scoped to an application or component instance.

For this use case, we have the createStoreContext primitive.

This primitive will create both a Provider and getter hook heavily typed to the store data passed in.


In this demo we have a global store that manages signals. We then generate the context APIs and pass the MyStore type so we obtain strict type accountability.

In our main component we use the StoreProvider and pass our store to the createStore prop.

In the child component we utilize the useStore hook to gain access to the store.

Note

Remember that anytime you want to read a signal from a primitive - you need to either use ReactiveText or useRead to subscribe to the signal.

API

createStoreContext doesn't accept any parameters and is essentially just a factory.

Return

createStoreContext returns an Object with two properties:

PropertyTypeDescription
StoreProviderElementTypeThe React Context Provider for the store.
useStore() => TA function to get the store context.
Copy
'use client'

import { HStack, Stack } from '@/styled-system/jsx'
import { Button, cerberus, For, Text } from '@cerberus/react'
import {
  Accessor,
  createSignal,
  createStoreContext,
  ReactiveText,
  useRead,
} from '@cerberus/signals'

type MyStore = {
  users: Accessor<string[]>
  selectedUser: Accessor<string | null>
  setSelectedUser: (user: string | null) => void
  addUser: (user: string) => void
}

function myStore(): MyStore {
  const [users, setUsers] = createSignal<string[]>([])
  const [selectedUser, setSelectedUser] = createSignal<string | null>(null)

  return {
    users,
    selectedUser,
    setSelectedUser: (user: string | null) => setSelectedUser(user),
    addUser: (newUser: string) => {
      setUsers([...users(), newUser])
    },
  }
}

const { StoreProvider, useStore } = createStoreContext<MyStore>()

// Components

export function BasicDemo() {
  return (
    <StoreProvider createStore={myStore}>
      <UserList />
    </StoreProvider>
  )
}

function UserList() {
  const store = useStore()
  const users = useRead(store.users)

  return (
    <Stack direction="column" gap="md" w="3/4">
      <Stack direction="column" gap="md" w="full">
        <Text>
          Selected: <ReactiveText data={store.selectedUser} />
        </Text>

        <Button
          size="sm"
          onClick={() => {
            store.addUser(crypto.randomUUID())
          }}
        >
          Add User
        </Button>
      </Stack>

      <cerberus.ul display="flex" flexDirection="column" gap="md" w="full">
        <For each={users}>
          {(user) => (
            <li key={user}>
              <HStack justify="space-between" w="full">
                {user}
                <Button size="sm" onClick={() => store.setSelectedUser(user)}>
                  Select
                </Button>
              </HStack>
            </li>
          )}
        </For>
      </cerberus.ul>
    </Stack>
  )
}

Selected: