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

Creating Effects

Learn how to create effects using Signals in React.

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

Usage

When you want to do something in response to a signal changing, you can use the creeateEffect primitive.

Effects come with the following benefits:

  1. Can be used anywhere in your application (e.g., not constrained to components)
  2. Can be nested within other effects
  3. Can be used within native React effects
  4. Auto-tracks signals (e.g., no dependency Array needed)

Basically, as long as the scope has access to a signal Accessor the usage is valid.

In this example, we utilize the createEffect to set the isEven signal value when getCount is updated.

Note

In order for createEffect to track signal subscriptions, it is required that Accessors are used in the body.

With React effects

You can nest createEffect within the native React effect when you need to access the React component render lifecycle.

Note

The createEffect primitive removes the overall need for native React effects.

The only time you should use native React effects is if you need to access the React component lifecycle. All other scenarios can be achieved using any of the primitive APIs this library offers.

API

createEffect accepts a callback Function and returns a Function. When the return Function is called, it will unsubscribe the effect from the signal Observer.

Important: be sure to use Accessor getters not values within a createEffect primitive. Ignoring to do so will cause stale values that will not be updated.

Copy
'use client'

import { HStack, Stack } from '@/styled-system/jsx'
import { Button, Text } from '@cerberus/react'
import { createComputed, createEffect, useSignal } from '@cerberus/signals'

export function BasicDemo() {
  const [count, setCount, getCount] = useSignal<number>(0)
  const [_isEven, setIsEven, getIsEven] = useSignal<boolean>(false)

  const info = createComputed(() => {
    return `${getCount()} is ${getIsEven() ? 'even' : 'odd'}`
  })

  createEffect(() => {
    setIsEven(getCount() % 2 === 0)
  })

  return (
    <HStack gap="xl" w="3/4">
      <Button onClick={() => setCount(count + 1)}>Increment</Button>

      <Stack direction="column" gap="xs">
        <Text>Count: {count}</Text>
        <Text>Double Count: {info()}</Text>
      </Stack>
    </HStack>
  )
}
Copy
'use client'

import { HStack } from '@/styled-system/jsx'
import { Button, Show, Text } from '@cerberus/react'
import { createEffect, useSignal } from '@cerberus/signals'
import { useEffect } from 'react'

function MountedMeta() {
  const [lifeCycle, setLifeCycle] = useSignal<string>('')
  const [count, setCount] = useSignal<number>(0)

  useEffect(() => {
    setLifeCycle('mounted')

    const unsubscribe = createEffect(() => {
      const interval = setInterval(() => {
        setCount((prev) => prev + 1)
      }, 1000)

      return () => clearInterval(interval)
    })

    return () => {
      setLifeCycle('unmounted')
      unsubscribe()
    }
  }, [setLifeCycle, setCount])

  return (
    <HStack gap="md" w="3/4">
      <Text>Component state: {lifeCycle}</Text>
      <Text>Count: {count}</Text>
    </HStack>
  )
}

export function NativeEffectDemo() {
  const [mount, setMount] = useSignal<boolean>(false)

  return (
    <HStack justify="space-between" w="3/4">
      <Button onClick={() => setMount((prev) => !prev)}>Toggle</Button>
      <Show when={mount}>{() => <MountedMeta />}</Show>
    </HStack>
  )
}

Count: 0

Double Count: 0 is even