UseIsMounted

In React 17 and earlier, calling a state setter after a component unmounted (for example, from a Promise that resolves after the user has navigated away) logged a console warning: Can't perform a React state update on an unmounted component. This useIsMounted hook guarded against that by tracking whether the component is still mounted before calling the setter.

React 18 removed that warning — calling a state setter after unmount is now a silent no-op, so this pattern is no longer needed just to silence it. The technique can still be useful if you specifically want to skip the async work's follow-up entirely once unmounted (not merely make the setter a no-op), but for most code you can rely on an AbortController or an effect cleanup flag instead.

Click "Toggle Book" and quickly unmount it before the 2-second timer finishes: thanks to the isMounted check, no state update (and no warning, even on React 17) happens after unmount.
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
const { useRef, useEffect, useState } = React;
function useIsMounted() {
  const isMounted = useRef(false);
  useEffect(() => {
    isMounted.current = true;
    return () => isMounted.current = false;
  }, []);
  return isMounted;
}
function asyncOperation() {
  return new Promise(resolve => setTimeout(() => resolve('data loaded'), 2000));
}
function Book() {
  const isMounted = useIsMounted();
  const [data, setData] = useState(null);
  useEffect(() => {
    asyncOperation().then(result => { if (isMounted.current) { setData(result); } });
  }, []);
  return <div>{data ? data : 'Loading...'}</div>;
}
function App() {
  const [show, setShow] = useState(true);
  return (
    <React.Fragment>
      <button onClick={() => setShow(s => !s)}>Toggle Book</button>
      {show && <Book/>}
    </React.Fragment>
  );
}
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<App/>);
</script>
</body></html>