[]previous and next page

useEffect

Runs a side effect after rendering and again whenever a tracked signal changes.

Runs a side effect after rendering and again whenever a tracked signal changes. The first run is deferred to the next flush. Effects never run on the server. Inside a <Suspense> boundary that is still showing its fallback, the first run waits until the boundary first shows its content.

Two forms: useEffect(fn) tracks everything fn reads; useEffect(deps, fn) tracks only deps and runs fn untracked. Return a function to clean up before the next run or disposal. An error thrown by the effect goes to the owner's error handler (onError, an error boundary). In development, an effect created outside any owner warns NO_OWNER_EFFECT: it still runs, but nothing can dispose it.

Explicit-dependency form of useEffect: tracks only what deps reads, and calls fn untracked with the new and the previous value of deps. Use it when the effect body reads signals that must not re-run it.

Import#

ts
import { useEffect } from "@shadow-js/core";

Signature#

ts
function useEffect(fn: () => void | Cleanup, options?: EffectOptions): void

function useEffect<T>(
  deps: () => T,
  fn: (value: T, previous: T | undefined) => void | Cleanup,
  options?: DeferredEffectOptions,
): void

Parameters#

Name Description
fn The effect. Every signal it reads is tracked. It may return a cleanup function.
options A devtools name. Undefined uses the default.
deps Tracked; its result is passed to fn.
fn Untracked; receives the value of deps and its previous value (undefined when there is none yet). It may return a cleanup function, which runs before the next call or on disposal.
options defer skips the first call; a devtools name. Undefined uses the defaults.

Examples#

ts
import { useEffect, useSignal } from "@shadow-js/core";

function PageTitle(props: { unread: number }) {
  const [title] = useSignal("Inbox");
  useEffect(() => {
    document.title = `${title()} (${props.unread})`; // re-runs when either changes
  });
  return null;
}
ts
import { useEffect } from "@shadow-js/core";

function Profile(props: { userId: string }) {
  useEffect(
    () => props.userId,
    (next, previous) => console.log(`switched from ${previous} to ${next}`),
    { defer: true }, // not called for the first id
  );
  return null;
}