Design React hooks to minimize unnecessary re-renders by avoiding common anti-patterns that cause performance issues. **Key principles:** 1. **Avoid umbrella hooks** - Don't create hooks that combine multiple responsibilities, especially mixing read and write operations. Split them into focused, single-purpose hooks.
Design React hooks to minimize unnecessary re-renders by avoiding common anti-patterns that cause performance issues.
Key principles:
Avoid umbrella hooks - Don’t create hooks that combine multiple responsibilities, especially mixing read and write operations. Split them into focused, single-purpose hooks.
Don’t return functions from hooks - Functions returned from hooks create new references on each render, triggering re-renders in consuming components. Instead, use utility functions defined outside React scope or stable callbacks with useRecoilCallback.
Minimize state dependencies - Use techniques like recoil callbacks with snapshot
and set
to avoid taking direct dependencies on state atoms, preventing re-renders when those states update.
Keep action hooks dependency-free - Hooks that perform actions (like create, update, delete) should typically not subscribe to state changes.
Example of problematic pattern:
// ❌ Bad: Umbrella hook with functions
export const useBillingPlan = () => {
const plans = useRecoilValue(plansState);
const getBaseLicensedPrice = (planKey) => {
// Function creates new reference each render
return plans.find(p => p.key === planKey);
};
return { plans, getBaseLicensedPrice };
};
Better approach:
// ✅ Good: Focused hooks with stable returns
export const usePlans = () => useRecoilValue(plansState);
export const useCreateWidget = () => {
return useRecoilCallback(({ snapshot, set }) => async (widgetData) => {
// No state dependencies, won't cause re-renders
const currentWidgets = await snapshot.getPromise(widgetsState);
set(widgetsState, [...currentWidgets, widgetData]);
});
};
Enter the URL of a public GitHub repository