Handling Side Effects & Working with the useEffect() HookEntry 1 of 7

What Side Effects Are

A side effect is any code that reaches outside the component's job of turning props and state into JSX.

Notes

A component function should be pure: the same props and state always produce the same JSX, and rendering changes nothing outside. Side effects break that rule, so they don't belong in the component body. Examples:

  • Fetching data or reading the user's location.
  • Reading or writing localStorage.
  • Setting timers or intervals.
  • Subscribing to events, sockets, or other external sources.
  • Calling DOM methods such as showModal() or focus().

A side effect in the component body runs on every render. If it also updates state, it triggers another render, which runs it again: an infinite loop.

What / Why / When

What

Work that affects or depends on something outside React's rendering.

Why it matters

Rendering must stay predictable; React may render a component many times.

When to care

Any time the code talks to the browser, the network, or a timer.

Use case

Sorting a list of places by distance from the user's current location.

Code compare

React
import { useEffect, useState } from "react";​type Place = { id: string; title: string; lat: number; lon: number };​export function App() {  const [availablePlaces, setAvailablePlaces] = useState<Place[]>([]);​  // ❌ In the body: runs every render, sets state, re-renders → infinite loop  // navigator.geolocation.getCurrentPosition((pos) => setAvailablePlaces(...));​  // ✅ In an effect: runs after the first render only  useEffect(() => {    navigator.geolocation.getCurrentPosition((position) => {      const sorted = sortPlacesByDistance(        AVAILABLE_PLACES,        position.coords.latitude,        position.coords.longitude,      );      setAvailablePlaces(sorted);    });  }, []);​  return <PlacesList places={availablePlaces} />;}

A class component is instantiated once, so one-time setup goes in ngOnInit (or the constructor):

Angular
import { Component, OnInit, signal } from "@angular/core";​@Component({  selector: "app-root",  template: `<app-places-list [places]="availablePlaces()" />`,})export class AppComponent implements OnInit {  availablePlaces = signal<Place[]>([]);​  ngOnInit() {    navigator.geolocation.getCurrentPosition((position) => {      this.availablePlaces.set(        sortPlacesByDistance(AVAILABLE_PLACES, position.coords.latitude, position.coords.longitude),      );    });  }}

Differences and gotchas

  • React re-runs the component function on every render, so it needs useEffect to control when side effects run. Angular's class runs once, so lifecycle hooks are enough for one-time setup.
  • Avoid side effects in Angular template expressions for the same reason: they run on every change detection pass.

Quick reference

ReactAngular
Side effect in useEffectngOnInit / constructor / effect()
Component body must stay pureTemplate expressions must stay pure