Note Custom hooks must start with 'use' so React can enforce the rules of hooks. They let you extract and share stateful logic between components without changing the component hierarchy.
custom hookextract logicreusable hookshare state logicuseLocalStorage
Compound Components
syntax
function Parent({ children }) { ... }
Parent.Child = function Child(props) { ... };
Note Compound components share implicit state via context, letting you create flexible APIs like <Select> + <Select.Option>. The parent manages state and children consume it without prop drilling.
compound componentscomponent apishared state childrenaccordion patternselect option pattern
Render Props
syntax
function DataProvider({ render }) {
const data = useData();
return render(data);
}
// or via children
<DataProvider>{(data) => <View data={data} />}</DataProvider>
example
function MouseTracker({ children }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
function handleMove(e) {
setPosition({ x: e.clientX, y: e.clientY });
}
window.addEventListener('mousemove', handleMove);
return () => window.removeEventListener('mousemove', handleMove);
}, []);
return children(position);
}
// Usage
<MouseTracker>
{({ x, y }) => (
<div>
Cursor is at ({x}, {y})
</div>
)}
</MouseTracker>
Note Render props are largely replaced by custom hooks, which are simpler. Still useful when you need to control what renders based on shared logic without creating a custom hook for every case.
render propsfunction as childrender callbackshared behavior
Error Boundaries
syntax
// Error boundaries must be class components (as of React 19)class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) { logError(error, info); }
render() {
if (this.state.hasError) return <Fallback />;
returnthis.props.children;
}
}
Note Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the tree below them. They do NOT catch errors in event handlers, async code, or server-side rendering. Use try/catch for those.
Note Portals render children into a different DOM node outside the parent hierarchy, but events still bubble through the React tree (not the DOM tree). Perfect for modals, tooltips, and dropdowns that need to escape overflow:hidden or z-index contexts.
Note React.lazy only works with default exports. For named exports, create an intermediate module that re-exports as default. Suspense can also wrap components that use the use() hook to read promises in React 19.
Note This pattern provides Redux-like state management with built-in React APIs. Splitting state and dispatch into separate contexts prevents components that only dispatch actions from re-rendering when state changes.
Note HOCs were the primary code reuse pattern before hooks. Custom hooks are now preferred for most cases because they are simpler and avoid the wrapper component nesting. HOCs are still useful for cross-cutting concerns like auth guards.
higher order componentHOCwrap componentwithAuthenhance component