You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Learn how to use createEffect to run side effects when reactive dependencies
16
16
change. Perfect for DOM manipulation and external library integration.
17
17
---
18
18
19
-
```tsx
20
-
import { createEffect } from"solid-js"
19
+
The `createEffect` primitive creates a reactive computation.
20
+
It automatically tracks reactive values, such as [signals](/concepts/signals), accessed within the provided function.
21
+
This function will re-run whenever any of its dependencies change.
21
22
22
-
function createEffect<T>(fn: (v:T) =>T, value?:T):void
23
+
## Execution Timing
23
24
24
-
```
25
+
### Initial Run
25
26
26
-
Effects are a general way to make arbitrary code ("side effects") run whenever dependencies change, e.g., to modify the DOM manually.
27
-
`createEffect` creates a new computation that runs the given function in a tracking scope, thus automatically tracking its dependencies, and automatically reruns the function whenever the dependencies update.
27
+
- The initial run of effects is **scheduled to occur after the current rendering phase completes**.
28
+
- It runs after all synchronous code in a component has finished and DOM elements have been created, but **before the browser paints them on the screen**.
29
+
-**[Refs](/concepts/refs) are set** before the first run, even though DOM nodes may not yet be attached to the main document tree.
30
+
This is relevant when using the [`children`](/reference/component-apis/children) helper.
28
31
29
-
For example:
32
+
### Subsequent Runs
30
33
31
-
```tsx
32
-
const [a, setA] =createSignal(initialValue)
34
+
- After the initial run, the effect **re-runs whenever any tracked dependency changes**.
35
+
- When multiple dependencies change within the same batch, the effect **runs once per batch**.
36
+
- The **order of runs** among multiple effects is **not guaranteed**.
37
+
- Effects always run **after** all pure computations (such as [memos](/concepts/derived-values/memos)) within the same update cycle.
33
38
34
-
// effect that depends on signal `a`
35
-
createEffect(() =>doSideEffect(a()))
36
-
```
39
+
### Server-Side Rendering
37
40
38
-
The effect will run whenever `a` changes value.
41
+
- Effects **never run during SSR**.
42
+
- Effects also **do not run during the initial client hydration**.
39
43
40
-
The effect will also run once, immediately after it is created, to initialize the DOM to the correct state. This is called the "mounting" phase.
41
-
However, we recommend using `onMount` instead, which is a more explicit way to express this.
44
+
## Import
42
45
43
-
The effect callback can return a value, which will be passed as the `prev` argument to the next invocation of the effect.
44
-
This is useful for memoizing values that are expensive to compute. For example:
46
+
```ts
47
+
import { createEffect } from"solid-js";
48
+
```
45
49
46
-
```tsx
47
-
const [a, setA] =createSignal(initialValue)
48
-
49
-
// effect that depends on signal `a`
50
-
createEffect((prevSum) => {
51
-
// do something with `a` and `prevSum`
52
-
const sum =a() +prevSum
53
-
if (sum!==prevSum) console.log("sum changed to", sum)
54
-
returnsum
55
-
}, 0)
56
-
// ^ the initial value of the effect is 0
50
+
## Type
51
+
52
+
```ts
53
+
function createEffect<Next>(
54
+
fn:EffectFunction<undefined|NoInfer<Next>, Next>
55
+
):void;
56
+
function createEffect<Next, Init=Next>(
57
+
fn:EffectFunction<Init|Next, Next>,
58
+
value:Init,
59
+
options?: { name?:string }
60
+
):void;
61
+
function createEffect<Next, Init>(
62
+
fn:EffectFunction<Init|Next, Next>,
63
+
value?:Init,
64
+
options?: { name?:string }
65
+
):void;
57
66
```
58
67
59
-
Effects are meant primarily for side effects that read but don't write to the reactive system: it's best to avoid setting signals in effects, which without care can cause additional rendering or even infinite effect loops. Instead, prefer using [createMemo](/reference/basic-reactivity/create-memo) to compute new values that depend on other reactive values, so the reactive system knows what depends on what, and can optimize accordingly.
60
-
If you do end up setting a signal within an effect, computations subscribed to that signal will be executed only once the effect completes; see [`batch`](/reference/reactive-utilities/batch) for more detail.
68
+
## Parameters
61
69
62
-
The first execution of the effect function is not immediate; it's scheduled to run after the current rendering phase (e.g., after calling the function passed to [render](/reference/rendering/render), [createRoot](/reference/reactive-utilities/create-root), or [runWithOwner](/reference/reactive-utilities/run-with-owner)).
63
-
If you want to wait for the first execution to occur, use [queueMicrotask](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) (which runs before the browser renders the DOM) or `await Promise.resolve()` or `setTimeout(..., 0)` (which runs after browser rendering).
70
+
### `fn`
64
71
65
-
```tsx
66
-
// assume this code is in a component function, so is part of a rendering phase
67
-
const [count, setCount] =createSignal(0)
68
-
69
-
// this effect prints count at the beginning and when it changes
It receives the value returned from the previous run, or the initial `value` during the first run.
78
+
The value returned by `fn` is passed to the next run.
79
+
80
+
### `value`
81
+
82
+
-**Type:**`Init`
83
+
-**Required:** No
90
84
91
-
This delay in first execution is useful because it means an effect defined in a component scope runs after the JSX returned by the component gets added to the DOM.
92
-
In particular, [refs](/reference/jsx-attributes/ref) will already be set.
93
-
Thus you can use an effect to manipulate the DOM manually, call vanilla JS libraries, or other side effects.
85
+
The initial value passed to `fn` during its first run.
94
86
95
-
Note that the first run of the effect still runs before the browser renders the DOM to the screen (similar to React's `useLayoutEffect`).
96
-
If you need to wait until after rendering (e.g., to measure the rendering), you can use `await Promise.resolve()` (or `Promise.resolve().then(...)`), but note that subsequent use of reactive state (such as signals) will not trigger the effect to rerun, as tracking is not possible after an async function uses `await`.
97
-
Thus you should use all dependencies before the promise.
87
+
### `options`
98
88
99
-
If you'd rather an effect run immediately even for its first run, use [createRenderEffect](/reference/secondary-primitives/create-render-effect) or [createComputed](/reference/secondary-primitives/create-computed).
89
+
-**Type:**`{ name?: string }`
90
+
-**Required:** No
91
+
92
+
An optional configuration object with the following properties:
93
+
94
+
#### `name`
95
+
96
+
-**Type:**`string`
97
+
-**Required:** No
98
+
99
+
A name for the effect, which can be useful for identification in debugging tools like the [Solid Debugger](https://github.com/thetarnav/solid-devtools).
You can clean up your side effects in between executions of the effect function by calling [onCleanup](/reference/lifecycle/on-cleanup) inside the effect function.
102
-
Such a cleanup function gets called both in between effect executions and when the effect gets disposed (e.g., the containing component unmounts).
103
-
For example:
129
+
### Execution Timing
104
130
105
131
```tsx
106
-
// listen to event dynamically given by eventName signal
// This is part of the component's synchronous execution.
138
+
console.log("Hello from counter");
139
+
140
+
// This effect is scheduled to run after the initial render is complete.
141
+
createEffect(() => {
142
+
console.log("Effect:", count());
143
+
});
144
+
145
+
// By contrast, a render effect runs synchronously during the render phase.
146
+
createRenderEffect(() => {
147
+
console.log("Render effect:", count());
148
+
});
149
+
150
+
// Setting a signal during the render phase re-runs render effects, but not effects, which are
151
+
// still scheduled.
152
+
setCount(1);
153
+
154
+
// A microtask is scheduled to run after the current synchronous code (the render phase) finishes.
155
+
queueMicrotask(() => {
156
+
// Now that rendering is complete, signal updates will trigger effects immediately.
157
+
setCount(2);
158
+
});
159
+
}
160
+
161
+
// Output:
162
+
// Hello from counter
163
+
// Render effect: 0
164
+
// Render effect: 1
165
+
// Effect: 1
166
+
// Render effect: 2
167
+
// Effect: 2
113
168
```
114
169
115
-
## Arguments
170
+
## Related
116
171
117
-
-`fn` - The function to run in a tracking scope. It can return a value, which will be passed as the `prev` argument to the next invocation of the effect.
118
-
-`value` - The initial value of the effect. This is useful for memoizing values that are expensive to compute.
0 commit comments