useEffect cleanup is not optional

    February 1, 20253 blocks

    The bug that taught me

    A subscription set up in an effect kept firing after the component unmounted. The fix is always the same: return a cleanup function and tear down whatever you set up.

    useEffect(() => {
      const sub = source.subscribe(onData);
      return () => sub.unsubscribe();
    }, [source]);