Runs a function immediately and re-runs it whenever any signal read inside it changes.
import { createEffect } from '@barefootjs/dom'
createEffect(fn: () => void | (() => void)): void#Basic Usage
const [count, setCount] = createSignal(0)
createEffect(() => {
document.title = `Count: ${count()}`
})
setCount(1) // Effect re-runs, title becomes "Count: 1"Dependencies are tracked automatically — every signal getter called during execution is recorded. No dependency array is needed.
#Automatic Dependency Tracking
The effect tracks whichever signals are actually read in each run. If a conditional branch skips a signal read, that signal is not a dependency for that run:
const [showName, setShowName] = createSignal(true)
const [name, setName] = createSignal('Alice')
const [count, setCount] = createSignal(0)
createEffect(() => {
if (showName()) {
console.log(name()) // name is tracked
} else {
console.log(count()) // count is tracked instead
}
})#Cleanup
Effects often set up resources that need to be torn down before the next run. There are two ways to register cleanup.
#Return a function
createEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000)
return () => clearInterval(timer)
})#`onCleanup`
createEffect(() => {
const timer = setInterval(() => console.log('tick'), 1000)
onCleanup(() => clearInterval(timer))
})onCleanup can be called multiple times. Cleanups run in reverse order (last registered, first called). See onCleanup for details.
#Common Patterns
#Syncing with localStorage
const [theme, setTheme] = createSignal('light')
createEffect(() => {
localStorage.setItem('theme', theme())
})#Fetching data
const [query, setQuery] = createSignal('')
createEffect(() => {
const q = query()
if (!q) return
const controller = new AbortController()
fetch(`/api/search?q=${q}`, { signal: controller.signal })
.then(r => r.json())
.then(setResults)
onCleanup(() => controller.abort())
})When query changes, the previous fetch is aborted before the new one starts.
#Updating DOM attributes
The compiler generates effects like this for reactive attributes:
// Source
<button disabled={!accepted()}>Submit</button>
// Generated client JS
createEffect(() => {
button.disabled = !accepted()
})