HOCs and Render Props

Higher-Order Components and Render Props

Before Hooks there was no way for two components to share stateful logic without sharing a parent. Two patterns filled the gap and are still in circulation. A higher-order component is a function that takes a component and returns a new one with extra props injected; a render prop is a prop whose value is a function the component calls to decide what to render. Compare all three solutions to one problem.

The same shared logic as a HOC, a render prop and a HookJavaScript
function withWidth(Wrapped) {                        // HOC: a component factory
  return function WithWidth(props) {
    const [w, setW] = useState(window.innerWidth);
    useEffect(() => {
      const on = () => setW(window.innerWidth);
      window.addEventListener('resize', on);
      return () => window.removeEventListener('resize', on);
    }, []);
    return <Wrapped {...props} width={w} />;         // pass through, then add
  };
}
const Bar = withWidth(({ width }) => <p>{width}px</p>);
function Width({ render }) {                         // render prop: call back to the caller
  const [w, setW] = useState(window.innerWidth);     // ...same effect as above
  return render(w);
}
const Bar2 = () => <Width render={(w) => <p>{w}px</p>} />;
// useWidth(): the same state and effect, returned as a plain value
const Bar3 = () => <p>{useWidth()}px</p>;            // Hook: no extra component at all

The differences show up at scale. Both older patterns add a component to the tree for every piece of logic shared, so a screen using five sits under five wrappers in DevTools — the "wrapper hell" that motivated Hooks. A HOC also hides the prop names it injects, so nothing tells you where width came from, and combining several means hoping their names do not collide. Render props avoid that but push the caller into a pyramid of nested callbacks. Hooks compose by ordinary variable names.

You still meet both: memo is a higher-order component, React 7,897 Redux 3,824 's connect and React Router 139,386 's old withRouter are HOCs, and drag-and-drop libraries expose render props because the parent must control what is drawn per item. Write new shared logic as a custom Hook. If you must write a HOC, name it withX, set its displayName, and never call it during a render — that remounts the subtree every time.