> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/preactjs/preact/llms.txt
> Use this file to discover all available pages before exploring further.

# useEffect

> Accepts a function that contains imperative, possibly effectful code

`useEffect` runs side effects after the component renders. Effects are scheduled to run after browser paint, without blocking the UI.

## Signature

```typescript theme={null}
function useEffect(
  effect: () => void | (() => void),
  inputs?: ReadonlyArray<unknown>
): void
```

## Parameters

<ParamField path="effect" type="() => void | (() => void)" required>
  A function containing the imperative, effectful code. Can optionally return a cleanup function that will be called before the effect runs again or when the component unmounts.
</ParamField>

<ParamField path="inputs" type="ReadonlyArray<unknown>" optional>
  An array of dependencies. The effect will only re-run if one of the values in this array has changed (compared using `===`). If omitted, the effect runs after every render.
</ParamField>

## Returns

`void`

## Basic Usage

```jsx theme={null}
import { useEffect, useState } from 'preact/hooks';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Update document title after render
    document.title = `Count: ${count}`;
  }, [count]); // Only re-run when count changes

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}
```

## Effect with Cleanup

```jsx theme={null}
function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);

    // Cleanup function
    return () => {
      clearInterval(interval);
    };
  }, []); // Empty array = run once on mount

  return <div>Seconds: {seconds}</div>;
}
```

## Fetching Data

```jsx theme={null}
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;

    async function fetchUser() {
      setLoading(true);
      try {
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        if (!cancelled) {
          setUser(data);
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }

    fetchUser();

    // Cleanup: prevent state updates if component unmounts
    return () => {
      cancelled = true;
    };
  }, [userId]); // Re-fetch when userId changes

  if (loading) return <div>Loading...</div>;
  return <div>{user?.name}</div>;
}
```

## Event Listeners

```jsx theme={null}
function WindowSize() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => {
      setWidth(window.innerWidth);
    };

    window.addEventListener('resize', handleResize);

    // Cleanup: remove listener on unmount
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // Empty deps = only setup/cleanup once

  return <div>Window width: {width}px</div>;
}
```

## Run Once on Mount

```jsx theme={null}
function InitialSetup() {
  useEffect(() => {
    console.log('Component mounted');

    return () => {
      console.log('Component will unmount');
    };
  }, []); // Empty dependency array

  return <div>Hello</div>;
}
```

## Multiple Effects

```jsx theme={null}
function MultipleEffects() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');

  // Effect for count
  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]);

  // Effect for name
  useEffect(() => {
    localStorage.setItem('name', name);
  }, [name]);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <input value={name} onChange={e => setName(e.target.value)} />
    </div>
  );
}
```

<Note>
  Effects run **after** the browser has painted, making them suitable for most side effects. For effects that must run synchronously before paint (like measuring DOM layout), use `useLayoutEffect` instead.
</Note>

<Note>
  Always include all values from the component scope that are used inside the effect in the dependency array. This ensures your effect always has the latest values.
</Note>

<Note>
  If your effect returns a cleanup function, it will be called before running the effect again (when dependencies change) and when the component unmounts.
</Note>
