React Lifecycle Methods

Loading

React components have a lifecycle that allows you to control what happens at different stages of a component’s existence. Here’s a breakdown of the key lifecycle phases and methods:

1. Mounting Phase (Component Creation)

Class Components

  • constructor() – Initializes state and binds methods
  • static getDerivedStateFromProps() – Updates state based on props (rarely used)
  • render() – Returns JSX to display
  • componentDidMount() – Runs after component is mounted to DOM (ideal for API calls, subscriptions)
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    fetchData().then(data => this.setState({ data }));
  }

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

Functional Components Equivalent

function Example() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then(setData);
  }, []); // Empty dependency array = runs once on mount

  return <div>{data}</div>;
}

2. Updating Phase (Re-rendering)

Class Components

  • static getDerivedStateFromProps() – Sync state to props
  • shouldComponentUpdate() – Optimize by preventing unnecessary renders
  • render() – Re-renders JSX
  • getSnapshotBeforeUpdate() – Capture DOM info before update
  • componentDidUpdate() – Runs after update completes
class Example extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.id !== this.props.id; // Only update if id changes
  }

  componentDidUpdate(prevProps) {
    if (this.props.id !== prevProps.id) {
      this.fetchData(this.props.id);
    }
  }
}

Functional Components Equivalent

function Example({ id }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchData(id).then(setData);
  }, [id]); // Re-runs only when id changes

  return <div>{data}</div>;
}

3. Unmounting Phase (Component Removal)

Class Components

  • componentWillUnmount() – Cleanup before removal (cancel timers, subscriptions)
class Example extends React.Component {
  componentDidMount() {
    this.timer = setInterval(() => {}, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }
}

Functional Components Equivalent

function Example() {
  useEffect(() => {
    const timer = setInterval(() => {}, 1000);
    return () => clearInterval(timer); // Cleanup function
  }, []);
}

4. Error Handling

Class Components

  • static getDerivedStateFromError() – Render fallback UI after error
  • componentDidCatch() – Log error information
class ErrorBoundary extends React.Component {
  state = { hasError: false };

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

  componentDidCatch(error, info) {
    logErrorToService(error, info);
  }
}

Functional Components Equivalent

(Requires class component for error boundaries – no hook equivalent yet)

Lifecycle Cheat Sheet

PhaseClass MethodHook Equivalent
MountingcomponentDidMount()useEffect(() => {}, [])
UpdatingcomponentDidUpdate()useEffect(() => {}, [deps])
UnmountingcomponentWillUnmount()useEffect(() => { return cleanup }, [])
State from PropsgetDerivedStateFromProps()useMemo, useState with props
Performance OptshouldComponentUpdate()React.memo, useMemo, useCallback

Key Takeaways

  1. Class components use explicit lifecycle methods
  2. Functional components use useEffect to handle most lifecycle needs
  3. useEffect combines componentDidMount, componentDidUpdate, and componentWillUnmount
  4. Error boundaries still require class components
  5. Modern React favors functional components with hooks

Leave a Reply

Your email address will not be published. Required fields are marked *