> ## 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.

# Lifecycle methods

> Learn about component lifecycle methods and when each method is called during a component's lifetime

Lifecycle methods are special methods that get called at different stages of a component's life. They allow you to run code when a component mounts, updates, or unmounts.

<Note>
  Lifecycle methods are only available in class components. Functional components use hooks like `useEffect` instead.
</Note>

## Component lifecycle phases

A component goes through three main phases:

1. **Mounting** - Component is created and inserted into the DOM
2. **Updating** - Component re-renders due to prop or state changes
3. **Unmounting** - Component is removed from the DOM

```mermaid theme={null}
graph LR
    A[Mounting] --> B[Updating]
    B --> B
    B --> C[Unmounting]
```

## Mounting phase

These methods are called when a component is being created and inserted into the DOM.

### constructor()

Called before the component is mounted. Used for initializing state and binding methods.

```jsx theme={null}
import { Component } from 'preact';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    this.increment = this.increment.bind(this);
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <button onClick={this.increment}>
        Count: {this.state.count}
      </button>
    );
  }
}
```

<Warning>
  Always call `super(props)` before accessing `this.props` in the constructor.
</Warning>

### componentWillMount()

<Warning>
  **Deprecated** - This method is called before mounting but is deprecated. Use `constructor()` or `componentDidMount()` instead.
</Warning>

Called immediately before mounting occurs. It's invoked during the diff process (`src/diff/index.js:168`):

```javascript theme={null}
if (
  isClassComponent &&
  newType.getDerivedStateFromProps == NULL &&
  c.componentWillMount != NULL
) {
  c.componentWillMount();
}
```

### componentDidMount()

Called immediately after the component is mounted. Perfect for:

* Fetching data from APIs
* Setting up subscriptions
* Adding event listeners
* Interacting with the DOM

Implementation in Preact (`src/diff/index.js:173`):

```javascript theme={null}
if (isClassComponent && c.componentDidMount != NULL) {
  c._renderCallbacks.push(c.componentDidMount);
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class UserProfile extends Component {
  state = { user: null, loading: true };

  componentDidMount() {
    fetch(`/api/users/${this.props.userId}`)
      .then(res => res.json())
      .then(user => {
        this.setState({ user, loading: false });
      });
  }

  render() {
    if (this.state.loading) {
      return <div>Loading...</div>;
    }

    return (
      <div>
        <h1>{this.state.user.name}</h1>
        <p>{this.state.user.email}</p>
      </div>
    );
  }
}
```

## Updating phase

These methods are called when a component's props or state change.

### getDerivedStateFromProps()

Static method called before rendering, both on initial mount and on updates. Returns an object to update state, or `null` to update nothing.

Implementation (`src/diff/index.js:148`):

```javascript theme={null}
if (isClassComponent && newType.getDerivedStateFromProps != NULL) {
  if (c._nextState == c.state) {
    c._nextState = assign({}, c._nextState);
  }

  assign(
    c._nextState,
    newType.getDerivedStateFromProps(newProps, c._nextState)
  );
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class EmailInput extends Component {
  state = { email: '', domain: '' };

  static getDerivedStateFromProps(props, state) {
    // Update domain when email changes
    if (props.email !== state.email) {
      const domain = props.email.split('@')[1] || '';
      return { email: props.email, domain };
    }
    return null;
  }

  render() {
    return (
      <div>
        <p>Email: {this.state.email}</p>
        <p>Domain: {this.state.domain}</p>
      </div>
    );
  }
}
```

<Info>
  `getDerivedStateFromProps` is static, so it doesn't have access to `this`. It's a pure function based only on props and state.
</Info>

### componentWillReceiveProps()

<Warning>
  **Deprecated** - Called when component receives new props. Use `getDerivedStateFromProps()` instead.
</Warning>

Called when a component receives new props (`src/diff/index.js:177`):

```javascript theme={null}
if (
  isClassComponent &&
  newType.getDerivedStateFromProps == NULL &&
  newProps !== oldProps &&
  c.componentWillReceiveProps != NULL
) {
  c.componentWillReceiveProps(newProps, componentContext);
}
```

### shouldComponentUpdate()

Called before rendering when new props or state are received. Return `false` to skip rendering.

Implementation (`src/diff/index.js:186`):

```javascript theme={null}
if (
  newVNode._original == oldVNode._original ||
  (!(c._bits & COMPONENT_FORCE) &&
    c.shouldComponentUpdate != NULL &&
    c.shouldComponentUpdate(
      newProps,
      c._nextState,
      componentContext
    ) === false)
) {
  // Skip rendering
  c.props = newProps;
  c.state = c._nextState;
  c._bits &= ~COMPONENT_DIRTY;
  // ...
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class UserCard extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    // Only update if user ID changed
    return this.props.userId !== nextProps.userId;
  }

  render() {
    return (
      <div className="user-card">
        <h3>User #{this.props.userId}</h3>
        <p>{this.props.name}</p>
      </div>
    );
  }
}
```

<Note>
  This is a powerful performance optimization. Use it to prevent unnecessary renders.
</Note>

### componentWillUpdate()

<Warning>
  **Deprecated** - Called immediately before rendering. Use `getSnapshotBeforeUpdate()` instead.
</Warning>

Called before rendering with new props or state (`src/diff/index.js:223`):

```javascript theme={null}
if (c.componentWillUpdate != NULL) {
  c.componentWillUpdate(newProps, c._nextState, componentContext);
}
```

### getSnapshotBeforeUpdate()

Called right before DOM updates are committed. Return value is passed to `componentDidUpdate()`.

Implementation (`src/diff/index.js:270`):

```javascript theme={null}
if (
  isClassComponent &&
  oldVNode._component &&
  c.getSnapshotBeforeUpdate != NULL
) {
  snapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class ChatBox extends Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Capture scroll position before update
    if (prevProps.messages.length < this.props.messages.length) {
      const list = this.listRef;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // Restore scroll position after update
    if (snapshot !== null) {
      const list = this.listRef;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={el => this.listRef = el}>
        {this.props.messages.map(msg => (
          <div key={msg.id}>{msg.text}</div>
        ))}
      </div>
    );
  }
}
```

### componentDidUpdate()

Called immediately after updating occurs. Good for:

* Operating on the DOM after an update
* Making network requests based on prop changes

Implementation (`src/diff/index.js:227`):

```javascript theme={null}
if (isClassComponent && c.componentDidUpdate != NULL) {
  c._renderCallbacks.push(() => {
    c.componentDidUpdate(oldProps, oldState, snapshot);
  });
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class UserData extends Component {
  state = { data: null };

  componentDidUpdate(prevProps) {
    // Fetch new data if userId changed
    if (this.props.userId !== prevProps.userId) {
      fetch(`/api/users/${this.props.userId}`)
        .then(res => res.json())
        .then(data => this.setState({ data }));
    }
  }

  render() {
    return <div>{this.state.data?.name}</div>;
  }
}
```

<Warning>
  Always compare props/state before making side effects in `componentDidUpdate()` to avoid infinite loops.
</Warning>

## Unmounting phase

### componentWillUnmount()

Called immediately before a component is unmounted and destroyed. Perfect for:

* Cleaning up timers
* Canceling network requests
* Removing event listeners
* Cleaning up subscriptions

Implementation (`src/diff/index.js:695`):

```javascript theme={null}
if ((r = vnode._component) != NULL) {
  if (r.componentWillUnmount) {
    try {
      r.componentWillUnmount();
    } catch (e) {
      options._catchError(e, parentVNode);
    }
  }

  r._parentDom = NULL;
}
```

#### Example usage

```jsx theme={null}
import { Component } from 'preact';

class Timer extends Component {
  state = { seconds: 0 };

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState({ seconds: this.state.seconds + 1 });
    }, 1000);
  }

  componentWillUnmount() {
    // Clean up interval
    clearInterval(this.interval);
  }

  render() {
    return <div>Seconds: {this.state.seconds}</div>;
  }
}
```

## Lifecycle method order

### On mount

1. `constructor()`
2. `getDerivedStateFromProps()`
3. `render()`
4. DOM updates
5. `componentDidMount()`

### On update

1. `getDerivedStateFromProps()`
2. `shouldComponentUpdate()`
3. `render()`
4. `getSnapshotBeforeUpdate()`
5. DOM updates
6. `componentDidUpdate()`

### On unmount

1. `componentWillUnmount()`
2. Component removed from DOM

## Complete lifecycle example

Here's a real-world example demonstrating multiple lifecycle methods:

```jsx theme={null}
import { Component } from 'preact';

class UserDashboard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: null,
      loading: true,
      error: null
    };
  }

  static getDerivedStateFromProps(props, state) {
    // Reset error when userId changes
    if (props.userId !== state.prevUserId) {
      return {
        prevUserId: props.userId,
        error: null
      };
    }
    return null;
  }

  componentDidMount() {
    this.fetchUser();
    // Set up polling
    this.pollInterval = setInterval(() => this.fetchUser(), 30000);
  }

  componentDidUpdate(prevProps) {
    // Fetch new user data if ID changed
    if (this.props.userId !== prevProps.userId) {
      this.fetchUser();
    }
  }

  componentWillUnmount() {
    // Clean up polling
    clearInterval(this.pollInterval);
    // Cancel any pending requests
    if (this.controller) {
      this.controller.abort();
    }
  }

  fetchUser = async () => {
    this.setState({ loading: true });
    this.controller = new AbortController();

    try {
      const response = await fetch(
        `/api/users/${this.props.userId}`,
        { signal: this.controller.signal }
      );
      const user = await response.json();
      this.setState({ user, loading: false, error: null });
    } catch (error) {
      if (error.name !== 'AbortError') {
        this.setState({ error, loading: false });
      }
    }
  };

  shouldComponentUpdate(nextProps, nextState) {
    // Only update if data actually changed
    return (
      this.props.userId !== nextProps.userId ||
      this.state.user !== nextState.user ||
      this.state.loading !== nextState.loading ||
      this.state.error !== nextState.error
    );
  }

  render() {
    const { loading, error, user } = this.state;

    if (loading && !user) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;
    if (!user) return <div>No user found</div>;

    return (
      <div className="dashboard">
        <h1>{user.name}</h1>
        <p>Email: {user.email}</p>
        <p>Role: {user.role}</p>
        {loading && <span className="updating">Updating...</span>}
      </div>
    );
  }
}
```

This example shows:

* Initializing state in `constructor()`
* Deriving state from props with `getDerivedStateFromProps()`
* Fetching data in `componentDidMount()`
* Updating when props change in `componentDidUpdate()`
* Cleaning up in `componentWillUnmount()`
* Optimizing with `shouldComponentUpdate()`

## Error boundaries

Error boundaries catch JavaScript errors anywhere in their component tree:

```jsx theme={null}
import { Component } from 'preact';

class ErrorBoundary extends Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    // Log error to error reporting service
    console.error('Error caught:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-boundary">
          <h1>Something went wrong</h1>
          <p>{this.state.error.message}</p>
        </div>
      );
    }

    return this.props.children;
  }
}

// Usage
<ErrorBoundary>
  <App />
</ErrorBoundary>
```

<Note>
  Error boundaries only catch errors in child components, not in the error boundary itself.
</Note>
