Lifecycle Hooks Deep Dive
Archibald provides several utility hooks to simplify common React lifecycle patterns and state tracking.
- useDidMount
- useWillMount
- useIsMounted
- useIsFirstRender
- useDeferredComponent
- How they work Step-by-Step
useDidMount
A semantic shortcut for useEffect(callback, []). It ensures the callback runs exactly once after the initial component mount.
useDidMount(() => {
console.log('Component has mounted!');
});
useWillMount
Executes a callback before the initial render. This hook is useful for setup logic that needs to happen before the DOM is created.
useWillMount(() => {
console.log('Component is about to mount!');
});
useIsMounted
Returns a stable MutableRefObject<boolean> that tracks whether the component is currently mounted in the DOM.
- Best Practice: Use this inside asynchronous operations (like
setTimeoutorPromise) to avoid updating state on an unmounted component.
const isMounted = useIsMounted();
const handleAsyncAction = async () => {
await someWork();
if (isMounted.current) {
setData(result);
}
};
useIsFirstRender
Returns a boolean that is true only during the very first render of the component.
const isFirst = useIsFirstRender();
if (isFirst) {
console.log('This is the initial render pass.');
}
useDeferredComponent
Dynamically imports a component and renders it only after the host has mounted on the client. Returns null on the server and the first client render (matching SSR — no hydration mismatch), then the loaded component once its import() resolves. The dynamic import is code-split by the bundler and only invoked post-hydration, so the component's code never ships in the initial/critical payload.
function Analytics() {
const Impl = useDeferredComponent(() => import('./AnalyticsImpl'));
return Impl ? <Impl /> : null;
}
Use it for no-UI client trackers or below-the-fold widgets that must stay out of the initial bundle. Unlike React.lazy + Suspense (which resolves during SSR/hydration and needs a boundary), the component here loads strictly after mount. The factory runs once on mount; a cleanup guard prevents a state update if the host unmounts before the import resolves.
How they work Step-by-Step
Scenario: useWillMount vs useDidMount
- Rendering Begins: React starts the initial render pass.
useWillMountcheck: The hook checks its internaluseRef. If it's the first run, it immediately executes the callback before anything is rendered.- Component Renders: The JSX is evaluated and the component is added to the DOM.
useDidMount(anduseEffect) Execution: After the DOM is updated, React runs theuseEffectcleanup/setup cycle.- Status Update:
useWillMountupdates its ref tofalsevia an internaluseDidMountcall, ensuring it doesn't run again.
Scenario: useIsMounted Tracking
- Hook Initialization: Returns a ref object initialized to
false. - Mounting: The component is added to the DOM. The
useEffectinside the hook runs, settingref.current = true. - Unmounting: The component is removed from the DOM. The cleanup function returned by the
useEffectruns, settingref.current = false.
Best Practice: While these hooks provide convenience, always prioritize standard React hooks (useEffect, useMemo) for core logic unless you specifically need the semantic clarity or specialized tracking these utilities provide.