Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f2293e5
Fix useSubmission
amirhhashemi May 16, 2025
bd691c2
Update
amirhhashemi Jun 8, 2025
1f94c98
Update
amirhhashemi Jun 11, 2025
b34f043
Update info callout titles (#1207)
amirhhashemi Jun 18, 2025
32333b3
update
amirhhashemi Jul 2, 2025
74f99ef
update
amirhhashemi Jul 3, 2025
629b1ed
update
amirhhashemi Aug 5, 2025
e08e037
update
amirhhashemi Aug 9, 2025
d6f6000
update
amirhhashemi Aug 14, 2025
1916db0
update
amirhhashemi Aug 16, 2025
d559c08
update
amirhhashemi Aug 23, 2025
3d54d72
update
amirhhashemi Aug 24, 2025
aeb0163
update
amirhhashemi Aug 25, 2025
ec29771
update
amirhhashemi Aug 25, 2025
0d10c42
update
amirhhashemi Aug 25, 2025
7afd42d
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
d2c7ddc
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
f9c71fa
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
af3cd09
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
9e376fd
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
6c81108
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
797c7a8
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
4e3075a
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
b40bf2b
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
fbe277e
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
97c13c4
Update src/routes/solid-router/concepts/queries.mdx
amirhhashemi Aug 26, 2025
442e9d1
Update src/routes/solid-start/guides/data-fetching.mdx
amirhhashemi Aug 26, 2025
c9fd477
Update src/routes/solid-start/guides/data-fetching.mdx
amirhhashemi Aug 26, 2025
eeae7d0
apply review results
amirhhashemi Aug 26, 2025
91c9178
experiment with new structure
amirhhashemi Aug 26, 2025
3e264be
Documentation metadata via Frontmatter (#1321)
davedbase Oct 28, 2025
3c6c41c
Additional changes to documentation metadata (#1328)
davedbase Oct 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/middleware/legacy-routes-redirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ const LEGACY_ROUTES = {

"/solid-router/reference/response-helpers/revalidate":
"/solid-router/reference/data-apis/revalidate",

"/solid-start/guides/data-loading": "/solid-start/guides/data-fetching",
} as const;

function isLegacyRoute(path: string): path is keyof typeof LEGACY_ROUTES {
Expand Down
6 changes: 0 additions & 6 deletions src/routes/concepts/effects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ createEffect(() => {
In this example, an effect is created that logs the current value of `count` to the console.
When the value of `count` changes, the effect is triggered, causing it to run again and log the new value of `count`.

:::note
Effects are primarily intended for handling side effects that do not write to the reactive system.
It's best to avoid setting signals within effects, as this can lead to additional rendering or even infinite loops if not managed carefully.
Instead, it is recommended to use [createMemo](/reference/basic-reactivity/create-memo) to compute new values that rely on other reactive values.
:::

## Managing dependencies

Effects can be set to observe any number of dependencies.
Expand Down
2 changes: 1 addition & 1 deletion src/routes/guides/routing-and-navigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ render(
```

`[id].jsx` contains the component that gets rendered.
When you wrap the function within [`createAsync`](/solid-router/reference/data-apis/create-async) with the imported function, it will yield [a signal](/concepts/signals) once the anticipated promise resolves.
When you wrap the function within [`createAsync`](/solid-router/reference/data-apis/create-async) with the imported function, it will yield [a signal](/routes/concepts/signals) once the anticipated promise resolves.

```jsx
// [id].jsx
Expand Down
212 changes: 78 additions & 134 deletions src/routes/reference/basic-reactivity/create-effect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,165 +10,109 @@ tags:
- reactivity
- lifecycle
- cleanup
version: "1.0"
version: '1.0'
description: >-
Learn how to use createEffect to run side effects when reactive dependencies
change. Perfect for DOM manipulation and external library integration.
---

The `createEffect` primitive creates a reactive computation.
It automatically tracks reactive values, such as [signals](/concepts/signals), accessed within the provided function.
This function will re-run whenever any of its dependencies change.

## Execution Timing

### Initial Run

- The initial run of effects is **scheduled to occur after the current rendering phase completes**.
- 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**.
- **[Refs](/concepts/refs) are set** before the first run, even though DOM nodes may not yet be attached to the main document tree.
This is relevant when using the [`children`](/reference/component-apis/children) helper.

### Subsequent Runs

- After the initial run, the effect **re-runs whenever any tracked dependency changes**.
- When multiple dependencies change within the same batch, the effect **runs once per batch**.
- The **order of runs** among multiple effects is **not guaranteed**.
- Effects always run **after** all pure computations (such as [memos](/concepts/derived-values/memos)) within the same update cycle.

### Server-Side Rendering

- Effects **never run during SSR**.
- Effects also **do not run during the initial client hydration**.

## Import
```tsx
import { createEffect } from "solid-js"

```ts
import { createEffect } from "solid-js";
```
function createEffect<T>(fn: (v: T) => T, value?: T): void

## Type

```ts
function createEffect<Next>(
fn: EffectFunction<undefined | NoInfer<Next>, Next>
): void;
function createEffect<Next, Init = Next>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
options?: { name?: string }
): void;
function createEffect<Next, Init>(
fn: EffectFunction<Init | Next, Next>,
value?: Init,
options?: { name?: string }
): void;
```

## Parameters

### `fn`

- **Type:** `EffectFunction<undefined | NoInfer<Next> | EffectFunction<Init | Next, Next>`
- **Required:** Yes
Effects are a general way to make arbitrary code ("side effects") run whenever dependencies change, e.g., to modify the DOM manually.
`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.

A function to be executed as the effect.
For example:

It receives the value returned from the previous run, or the initial `value` during the first run.
The value returned by `fn` is passed to the next run.

### `value`

- **Type:** `Init`
- **Required:** No

The initial value passed to `fn` during its first run.
```tsx
const [a, setA] = createSignal(initialValue)

### `options`
// effect that depends on signal `a`
createEffect(() => doSideEffect(a()))
```

- **Type:** `{ name?: string }`
- **Required:** No
The effect will run whenever `a` changes value.

An optional configuration object with the following properties:
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.
However, we recommend using `onMount` instead, which is a more explicit way to express this.

#### `name`
The effect callback can return a value, which will be passed as the `prev` argument to the next invocation of the effect.
This is useful for memoizing values that are expensive to compute. For example:

- **Type:** `string`
- **Required:** No
```tsx
const [a, setA] = createSignal(initialValue)

// effect that depends on signal `a`
createEffect((prevSum) => {
// do something with `a` and `prevSum`
const sum = a() + prevSum
if (sum !== prevSum) console.log("sum changed to", sum)
return sum
}, 0)
// ^ the initial value of the effect is 0
```

A name for the effect, which can be useful for identification in debugging tools like the [Solid Debugger](https://github.com/thetarnav/solid-devtools).
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.
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.

## Return value
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)).
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).

`createEffect` does not return a value.
```tsx
// assume this code is in a component function, so is part of a rendering phase
const [count, setCount] = createSignal(0)

// this effect prints count at the beginning and when it changes
createEffect(() => console.log("count =", count()))
// effect won't run yet
console.log("hello")
setCount(1) // effect still won't run yet
setCount(2) // effect still won't run yet

queueMicrotask(() => {
// now `count = 2` will print
console.log("microtask")
setCount(3) // immediately prints `count = 3`
console.log("goodbye")
})

// --- overall output: ---
// hello
// count = 2
// microtask
// count = 3
// goodbye
```

## Examples
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.
In particular, [refs](/reference/jsx-attributes/ref) will already be set.
Thus you can use an effect to manipulate the DOM manually, call vanilla JS libraries, or other side effects.

### Basic Usage
Note that the first run of the effect still runs before the browser renders the DOM to the screen (similar to React's `useLayoutEffect`).
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`.
Thus you should use all dependencies before the promise.

```tsx
import { createSignal, createEffect } from "solid-js";

function Counter() {
const [count, setCount] = createSignal(0);

// Every time count changes, this effect re-runs.
createEffect(() => {
console.log("Count incremented! New value: ", count());
});

return (
<div>
<p>Count: {count()}</p>
<button onClick={() => setCount((prev) => prev + 1)}>Increment</button>
</div>
);
}
```
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).

### Execution Timing
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.
Such a cleanup function gets called both in between effect executions and when the effect gets disposed (e.g., the containing component unmounts).
For example:

```tsx
import { createSignal, createEffect, createRenderEffect } from "solid-js";

function Counter() {
const [count, setCount] = createSignal(0);

// This is part of the component's synchronous execution.
console.log("Hello from counter");

// This effect is scheduled to run after the initial render is complete.
createEffect(() => {
console.log("Effect:", count());
});

// By contrast, a render effect runs synchronously during the render phase.
createRenderEffect(() => {
console.log("Render effect:", count());
});

// Setting a signal during the render phase re-runs render effects, but not effects, which are
// still scheduled.
setCount(1);

// A microtask is scheduled to run after the current synchronous code (the render phase) finishes.
queueMicrotask(() => {
// Now that rendering is complete, signal updates will trigger effects immediately.
setCount(2);
});
}

// Output:
// Hello from counter
// Render effect: 0
// Render effect: 1
// Effect: 1
// Render effect: 2
// Effect: 2
// listen to event dynamically given by eventName signal
createEffect(() => {
const event = eventName()
const callback = (e) => console.log(e)
ref.addEventListener(event, callback)
onCleanup(() => ref.removeEventListener(event, callback))
})
```

## Related
## Arguments

- [`createRenderEffect`](/reference/secondary-primitives/create-render-effect)
- [`onCleanup`](/reference/lifecycle/on-cleanup)
- [`onMount`](/reference/lifecycle/on-mount)
- `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.
- `value` - The initial value of the effect. This is useful for memoizing values that are expensive to compute.
Loading