# Advanced React > The Advanced React book by Nadia Makarevich: 16 chapters and 105 interactive, runnable code examples on how React really works. Re-renders, elements as props, render props, memoization, reconciliation and keys, higher-order components, context and performance, refs and imperative APIs, closures, debouncing and throttling, useLayoutEffect, portals, data fetching, race conditions, and error handling. Author: Nadia Makarevich. Bio at https://www.advanced-react.com/about. Blog at https://www.developerway.com. The DRM-free ebook (PDF + EPUB) is $35. Also on Amazon as paperback, hardcover, and Kindle. A free sample chapter is available by email. Regional pricing code: PARITY20 (20% off). Machine-readable archive (including example source code) at https://www.advanced-react.com/examples.json. XML sitemap at https://www.advanced-react.com/sitemap.xml. Markdown sitemap at https://www.advanced-react.com/sitemap.md. ## Pages - [Home](https://www.advanced-react.com/): the book, what it covers, pricing, and reviews. - [What's inside](https://www.advanced-react.com/whats-inside): the full table of contents, every chapter and section. - [Code examples](https://www.advanced-react.com/examples): all 105 interactive examples, runnable in the browser. - [About Nadia Makarevich](https://www.advanced-react.com/about): the author's bio. ## Table of contents - Introduction: how to read this book - Chapter 1. Intro to re-renders - Chapter 2. Elements, children as props, and re-renders - Chapter 3. Configuration concerns with elements as props - Chapter 4. Advanced configuration with render props - Chapter 5. Memoization with useMemo, useCallback and React.memo - Chapter 6. Deep dive into diffing and reconciliation - Chapter 7. Higher-order components in modern world - Chapter 8. React Context and performance - Chapter 9. Refs: from storing data to imperative API - Chapter 10. Closures in React - Chapter 11. Implementing advanced debouncing and throttling with Refs - Chapter 12. Escaping Flickering UI with useLayoutEffect - Chapter 13. React portals and why do we need them - Chapter 14. Data fetching on the client and performance - Chapter 15. Data fetching and race conditions - Chapter 16. Universal error handling in React ## Interactive code examples ### Chapter 1. Intro to re-renders - [Example 1: The re-render problem](https://www.advanced-react.com/examples/01/01): Opening a modal whose state lives at the top of the app re-renders every component below it, so a trivial dialog takes almost a second to appear. - [Example 2: The big re-renders myth](https://www.advanced-react.com/examples/01/02): Mutating a plain local variable instead of calling a state setter never re-renders, so the dialog never opens. Props changing don't cause re-renders; state updates do. - [Example 3: Moving state down](https://www.advanced-react.com/examples/01/03): Extracting the button, the dialog, and their state into a small child component keeps the re-render contained, and the dialog now opens instantly. - [Example 4: State in a custom hook](https://www.advanced-react.com/examples/01/04): Hiding the modal state inside a useModalDialog hook still re-renders the whole component on every change: a hook abstracts state away but doesn't isolate it. - [Example 5: Hidden state in a hook](https://www.advanced-react.com/examples/01/05): A custom hook that tracks window resize re-renders the entire app on every resize, even though the width value is never returned from the hook. - [Example 6: Hooks calling hooks](https://www.advanced-react.com/examples/01/06): Even a hook that returns null re-renders its host: any state update anywhere in a chain of hooks re-renders the component that uses the first one. - [Example 7: Isolating the hook](https://www.advanced-react.com/examples/01/07): The fix: move the button, dialog, and the custom hook into one small component so resize-driven re-renders stay contained instead of reaching the whole app. ### Chapter 2. Elements, children as props, and re-renders - [Example 1: The scroll re-render problem](https://www.advanced-react.com/examples/02/01): Saving scroll position to state in the component that wraps the slow content re-renders all of it on every scroll, making scrolling laggy. - [Example 2: Passing elements as props](https://www.advanced-react.com/examples/02/02): Moving the scroll state into its own component and passing the slow content in as a prop keeps that content out of the re-render, so scrolling stays smooth. - [Example 3: Children as props](https://www.advanced-react.com/examples/02/03): Rewriting the content prop as JSX children nesting gives the same re-render protection with cleaner composition syntax, since children are just props. ### Chapter 3. Configuration concerns with elements as props - [Example 1: Icon as an element prop](https://www.advanced-react.com/examples/03/01): Replacing a Button's many icon configuration props with a single icon element prop lets the consumer pass any configured icon, like Loading or an Avatar. - [Example 2: Footer prop on a dialog](https://www.advanced-react.com/examples/03/02): A ModalDialog exposes a footer prop so the consumer can pass one button, two buttons, or any element arrangement without dedicated configuration props. - [Example 3: Layout slots accept anything](https://www.advanced-react.com/examples/03/03): A ThreeColumnsLayout takes leftColumn, middleColumn, and rightColumn element props, rendering whatever the consumer supplies in each slot with no configuration. - [Example 4: Content as children](https://www.advanced-react.com/examples/03/04): Renaming the dialog's content prop to children lets the main area be passed with nested JSX syntax, which is just sugar for the children prop. - [Example 5: Default props via cloneElement](https://www.advanced-react.com/examples/03/05): The Button clones its icon with cloneElement, merging default size and color from its own props while letting the icon's own props override them. - [Example 6: Overriding props by mistake](https://www.advanced-react.com/examples/03/06): Cloning the icon with default props applied after, not before, the icon's own props destroys its API, so a passed color like red never reaches the icon. ### Chapter 4. Advanced configuration with render props - [Example 1: Render prop for an icon](https://www.advanced-react.com/examples/04/01): Passing the icon as a render function lets Button hand default props into it, so the consumer can spread, override, or remap them onto any icon library. - [Example 2: Sharing state through render props](https://www.advanced-react.com/examples/04/02): Button keeps its own hovered state and passes it to the render function, so the consumer can swap icons or change classNames based on that state. - [Example 3: Children as a render function](https://www.advanced-react.com/examples/04/03): Making children a function instead of an element means Parent calls children() to render it, and the nested JSX syntax still works the same way. - [Example 4: Sharing stateful logic](https://www.advanced-react.com/examples/04/04): ResizeDetector tracks window width and passes it through children as a function, so consuming components read the width directly without holding their own state. - [Example 5: Replacing render props with hooks](https://www.advanced-react.com/examples/04/05): Moving the resize logic into a useResizeDetector hook returns the width directly, replacing the render prop with less code that is easier to follow. - [Example 6: Render props tied to a DOM element](https://www.advanced-react.com/examples/04/06): ScrollDetector attaches onScroll to its own div and passes the scroll position through children, a case where render props still beat a hook. ### Chapter 5. Memoization with useMemo, useCallback and React.memo - [Example 1: useMemo versus useCallback](https://www.advanced-react.com/examples/05/01): Wrapping a function in useCallback or returning it from useMemo keeps its reference stable, so a useEffect that depends on it stops firing on every re-render. - [Example 2: Memoized props for React.memo](https://www.advanced-react.com/examples/05/02): Wrapping a child in React.memo and memoizing its object and function props with useMemo and useCallback gives stable references, so the child stops re-rendering. - [Example 3: Spread props break memoization](https://www.advanced-react.com/examples/05/03): A parent spreading a non-memoized data prop through intermediate components breaks the React.memo check on the child below, so it re-renders anyway. - [Example 4: Custom hooks break memoization](https://www.advanced-react.com/examples/05/04): Passing a submit function returned from a custom hook to a React.memo child breaks its memoization, since the hook re-creates that function on every re-render. - [Example 5: Children as a prop](https://www.advanced-react.com/examples/05/05): JSX children passed to a React.memo component are a non-memoized object that breaks the props check, so wrapping the child element in useMemo restores memoization. - [Example 6: Memoizing render prop children](https://www.advanced-react.com/examples/05/06): When children is a function re-created each render, memoizing it with useMemo or useCallback keeps the reference stable so the React.memo wrapper still works. - [Example 7: Nested memoized children](https://www.advanced-react.com/examples/05/07): Nesting one memoized component inside another still breaks the parent memoization, since the child element is an unmemoized object until wrapped in useMemo. ### Chapter 6. Deep dive into diffing and reconciliation - [Example 1: Conditional inputs share state](https://www.advanced-react.com/examples/06/01): Swapping between two Input components of the same type in a ternary makes React re-render rather than remount, so typed text leaks across the conditional. - [Example 2: Components defined inside components](https://www.advanced-react.com/examples/06/02): Declaring a component inside another recreates its function on every render, so React remounts it each keystroke and its active state is lost. - [Example 3: Fixing the bug with arrays](https://www.advanced-react.com/examples/06/03): Rendering each conditional input in its own array slot with a null sibling gives them stable positions, so switching now unmounts one and mounts the other. - [Example 4: Key identifies list items](https://www.advanced-react.com/examples/06/04): Reordering a dynamic list without keys keeps state tied to position, while adding a key makes React move the matching DOM node and its typed text along. - [Example 5: Key with memoized lists](https://www.advanced-react.com/examples/06/05): Reordering a memoized list keyed by array index still re-renders items because props shift, while keying by stable id lets React swap nodes without re-rendering. - [Example 6: State reset with key](https://www.advanced-react.com/examples/06/06): Giving the two conditional inputs different key values forces React to unmount and remount on switch, resetting the field so typed text no longer carries over. - [Example 7: Force reuse with shared key](https://www.advanced-react.com/examples/06/07): Putting the same key on inputs rendered in different array positions makes React reuse one instance across the switch, preserving its state and DOM. - [Example 8: Keys outside dynamic arrays](https://www.advanced-react.com/examples/06/08): Toggling which of two non-list inputs holds a shared key makes React reuse one instance at the keyed position, so the typed text jumps between fields. ### Chapter 7. Higher-order components in modern world - [Example 1: Injecting props with a HOC](https://www.advanced-react.com/examples/07/01): A withTheme higher-order component reads the current theme and injects it as a theme prop into a wrapped button without changing the button's code. - [Example 2: Enhancing callbacks](https://www.advanced-react.com/examples/07/02): A withLoggingOnClick HOC intercepts a component onClick callback to fire logging events, then reuses the same logic on a Button and a ListItem unchanged. - [Example 3: Passing data to a HOC](https://www.advanced-react.com/examples/07/03): Logging text reaches the HOC two ways: as a second function argument fixed per wrapped component, or as a prop on the resulting component set per use. - [Example 4: Enhancing lifecycle events](https://www.advanced-react.com/examples/07/04): HOCs use useEffect internally to log on mount and to log again whenever a watched id prop changes, since the returned wrapper is just a component. - [Example 5: Intercepting DOM events](https://www.advanced-react.com/examples/07/05): A withSuppressKeyPress HOC wraps any component in a div with onKeyPress calling stopPropagation, blocking global keyboard shortcuts while a modal is open. ### Chapter 8. React Context and performance - [Example 1: Lifting state up](https://www.advanced-react.com/examples/08/01): Storing the sidebar's expand state in the top Page component re-renders the whole tree on every toggle, making collapse slow and laggy. - [Example 2: Passing state through Context](https://www.advanced-react.com/examples/08/02): Moving the navigation state into a Context provider lets only the components that call useContext re-render, so the slow middle tree stays untouched. - [Example 3: Provider re-render problem](https://www.advanced-react.com/examples/08/03): An unrelated scroll state in a parent above the provider re-creates its value object, so every Context consumer re-renders on each scroll event. - [Example 4: Memoizing the value](https://www.advanced-react.com/examples/08/04): Wrapping the provider value in useMemo and the toggle in useCallback keeps the reference stable, so consumers stop re-rendering when the parent re-renders. - [Example 5: Splitting providers](https://www.advanced-react.com/examples/08/05): Separating the changing state and the stable open and close functions into two Contexts lets components that only use the API skip state-change re-renders. - [Example 6: Reducers and stable API](https://www.advanced-react.com/examples/08/06): Switching from useState to useReducer makes toggle, open, and close dispatch actions without depending on state, so the api value never changes. - [Example 7: Context selectors via HOC](https://www.advanced-react.com/examples/08/07): A higher-order component that reads Context and wraps the target in React.memo lets a heavy component use a Context value without re-rendering on changes. ### Chapter 9. Refs: from storing data to imperative API - [Example 1: Storing input value in a ref](https://www.advanced-react.com/examples/09/01): Saving the input value to ref.current in onChange instead of state works for a basic submit, showing how a ref persists data between re-renders. - [Example 2: Ref update skips re-render](https://www.advanced-react.com/examples/09/02): A character count read from ref.current stays at zero while typing and only updates when opening the modal forces an unrelated re-render. - [Example 3: Ref value not seen by children](https://www.advanced-react.com/examples/09/03): A ref value passed as the search prop never reaches the child component, since the ref update triggers no re-render to propagate the new value down. - [Example 4: Refs for non-rendered data](https://www.advanced-react.com/examples/09/04): A usePrevious hook stores the prior value in a ref and a render counter increments in useEffect, showing valid ref uses that never feed rendering. - [Example 5: Focusing a DOM element via ref](https://www.advanced-react.com/examples/09/05): Attaching a ref to an input lets the form call ref.current.focus() on submit to focus the empty field, accessing the real DOM element directly. - [Example 6: Passing a ref as a prop](https://www.advanced-react.com/examples/09/06): The form creates a ref and passes it to InputField as a regular prop, which attaches it to its input so the parent can focus the child's DOM element. - [Example 7: Forwarding refs with forwardRef](https://www.advanced-react.com/examples/09/07): Wrapping InputField in forwardRef lets the form pass an actual ref prop, injecting it as the second argument so it attaches to the inner input. - [Example 8: Imperative API with useImperativeHandle](https://www.advanced-react.com/examples/09/08): useImperativeHandle attaches a custom object with focus and shake methods to the ref, exposing a clean API and hiding the input DOM details. - [Example 9: Imperative API by mutating the ref](https://www.advanced-react.com/examples/09/09): Assigning the focus and shake API object directly to apiRef.current inside useEffect reproduces useImperativeHandle without the hook. ### Chapter 10. Closures in React - [Example 1: The stale closure bug](https://www.advanced-react.com/examples/10/01): A memoized form whose comparison function checks only the title freezes the onClick closure, so the submitted value always logs as undefined. - [Example 2: Caching a closure](https://www.advanced-react.com/examples/10/02): Storing a returned function in an external cache freezes its captured value, and comparing the previous value before refreshing the cache fixes it. - [Example 3: useCallback dependencies](https://www.advanced-react.com/examples/10/03): A useCallback with an empty dependency array never refreshes its closure, so the state read inside the callback stays stuck at its initial value. - [Example 4: Stale closures in Refs](https://www.advanced-react.com/examples/10/04): A callback stored in useRef captures props and state only once at mount, so updating ref.current inside an effect keeps the closure current. - [Example 5: Escaping the closure trap](https://www.advanced-react.com/examples/10/05): An effect refreshes ref.current every render while a stable empty useCallback calls it, giving onClick the latest state without breaking memoization. ### Chapter 11. Implementing advanced debouncing and throttling with Refs - [Example 1: Debounce versus throttle](https://www.advanced-react.com/examples/11/01): An auto-save field compares debounce and throttle: debounce fires once after typing stops, while throttle saves periodically so less work is lost on a crash. - [Example 2: Debounce recreated on render](https://www.advanced-react.com/examples/11/02): Calling debounce on every keystroke while updating state only delays each request instead of debouncing, so every typed character still hits the backend. - [Example 3: Memoizing the debounced call](https://www.advanced-react.com/examples/11/03): Wrapping the callback in useCallback and the debounce call in useMemo preserves one timer across re-renders, so the request is debounced correctly again. - [Example 4: Stale state from dependencies](https://www.advanced-react.com/examples/11/04): Reading state inside the callback adds it to useCallback dependencies, which recreates the debounced function on every change and degrades it back to a delay. - [Example 5: Naive Ref with useEffect](https://www.advanced-react.com/examples/11/05): Storing the debounced function in a Ref and reassigning it in useEffect on state change recreates the timer each time, so debounce is again just a delay. - [Example 6: The useDebounce hook](https://www.advanced-react.com/examples/11/06): Keeping the latest callback in a Ref updated via useEffect and debouncing a stable wrapper once gives a useDebounce hook with access to fresh state. ### Chapter 12. Escaping Flickering UI with useLayoutEffect - [Example 1: Flickering responsive navigation](https://www.advanced-react.com/examples/12/01): Measuring link widths in useEffect and hiding overflow items runs as a separate task, so the browser paints the full menu first and the layout visibly flickers. - [Example 2: Fixing flicker with useLayoutEffect](https://www.advanced-react.com/examples/12/02): Swapping useEffect for useLayoutEffect runs the measurement and state update synchronously before paint, so the navigation trims items with no visible flash. - [Example 3: Blocking synchronous painting](https://www.advanced-react.com/examples/12/03): Changing an element border three times with synchronous delays in one task stops the browser painting until the end, so only the final black border appears. - [Example 4: Splitting work with setTimeout](https://www.advanced-react.com/examples/12/04): Wrapping each border change in setTimeout breaks the work into separate tasks, letting the browser repaint between them so the color transition is visible. ### Chapter 13. React portals and why do we need them - [Example 1: Absolute positioning a dialog](https://www.advanced-react.com/examples/13/01): Applying position absolute to a modal lifts it out of document flow and, with top and left, centers it on the page when no positioned parent gets in the way. - [Example 2: Absolute is actually relative](https://www.advanced-react.com/examples/13/02): Placing the same absolute dialog inside a position relative div centers it within that div instead of the screen, since absolute positions against its nearest positioned parent. - [Example 3: z-index and stacking context](https://www.advanced-react.com/examples/13/03): Adding position and z-index to a parent div creates an isolated stacking context, so the trapped dialog stays under a sibling no matter how high its own z-index goes. - [Example 4: Overflow clipping a dialog](https://www.advanced-react.com/examples/13/04): An absolutely positioned dialog gets clipped only when its parent combines overflow with position, demonstrating that overflow alone does not cut off positioned children. - [Example 5: Fixed cannot escape stacking](https://www.advanced-react.com/examples/13/05): A position fixed dialog escapes overflow but still renders beneath a higher z-index sibling, proving nothing can break out of a parent stacking context. - [Example 6: The stacking context trap](https://www.advanced-react.com/examples/13/06): A realistic layout with a sticky z-index header and translated panels breaks the dialog, which now mispositions and slides under the header from the stacking trap. - [Example 7: Fixing it with createPortal](https://www.advanced-react.com/examples/13/07): Wrapping the dialog in createPortal renders it into the root element outside the trap, so it centers correctly and sits on top of the sticky header again. - [Example 8: Portals and React behavior](https://www.advanced-react.com/examples/13/08): A portalled dialog still inherits Context, re-renders with its parent, and bubbles its synthetic click up the React tree, since what happens in React stays in React. - [Example 9: Portals and DOM behavior](https://www.advanced-react.com/examples/13/09): The portalled dialog ignores native addEventListener and form onSubmit from its React parent, because outside React those events follow the actual DOM structure. ### Chapter 14. Data fetching on the client and performance - [Example 1: Load everything at once](https://www.advanced-react.com/examples/14/01): Fetching sidebar, issue, and comments together at the root and holding one loading screen until all arrive renders the whole page in a single step. - [Example 2: Sidebar first](https://www.advanced-react.com/examples/14/02): Loading the sidebar at the root and the issue plus its comments inside the Issue component shows the sidebar first, then the main content together. - [Example 3: Issue first, piece by piece](https://www.advanced-react.com/examples/14/03): Loading the issue at the root, then the sidebar, then comments inside Issue reveals each section as its own data arrives, breaking the top-left reading flow. - [Example 4: Six requests block the app](https://www.advanced-react.com/examples/14/04): Firing six slow requests before the App component, without awaiting them, exhausts Chrome's parallel connection limit so even a fast fetch waits behind them. - [Example 5: Classic request waterfall](https://www.advanced-react.com/examples/14/05): Co-locating fetches in nested components that each return loading until their data arrives chains the requests in sequence, making the whole app the slowest of all. - [Example 6: Promise.all at the root](https://www.advanced-react.com/examples/14/06): Lifting all three fetches into the root and awaiting them together with Promise.all fires them in parallel, cutting total wait to the slowest single request. - [Example 7: Parallel promises resolved independently](https://www.advanced-react.com/examples/14/07): Firing the three fetches in parallel but saving each in its own then callback lets sidebar, issue, and comments render the moment their data lands. - [Example 8: Data providers with Context](https://www.advanced-react.com/examples/14/08): Wrapping the app in Context-based data providers fetches each request in parallel up top while components read their data via hooks, removing props drilling. - [Example 9: Fetching before React](https://www.advanced-react.com/examples/14/09): Starting the comments fetch as a module-level promise outside the component fires it before any useEffect, shortening the waterfall but escaping React control. ### Chapter 15. Data fetching and race conditions - [Example 1: The race condition demo](https://www.advanced-react.com/examples/15/01): A tabbed app fetches each tab data in useEffect, so navigating quickly between tabs makes the content blink and load seemingly at random. - [Example 2: Stale fetch overwrites fresh](https://www.advanced-react.com/examples/15/02): Navigating forward then quickly back lets the slow first fetch resolve last, so its setData overwrites the correct data with stale content. - [Example 3: Re-mounting avoids the race](https://www.advanced-react.com/examples/15/03): Conditionally rendering separate page components unmounts the old one, so its in-flight fetch can no longer call setData and the race never happens. - [Example 4: Compare result id via ref](https://www.advanced-react.com/examples/15/04): Storing the latest id in a ref lets the then callback ignore any fetch result whose returned id no longer matches the active page. - [Example 5: Compare result url via ref](https://www.advanced-react.com/examples/15/05): When results carry no id, a ref holds the latest url and the callback drops any response whose url does not match the current request. - [Example 6: Cleanup closure flag](https://www.advanced-react.com/examples/15/06): The useEffect cleanup flips an isActive closure variable to false, so each stale fetch sees its flag cleared and skips the setData call. - [Example 7: Cancel with AbortController](https://www.advanced-react.com/examples/15/07): Passing an AbortController signal to fetch and calling abort in cleanup cancels in-flight requests so only the newest one resolves and sets state. - [Example 8: Async/await same race](https://www.advanced-react.com/examples/15/08): Rewriting the fetching with async/await produces the identical race condition, since await is just nicer syntax over the same asynchronous promises. ### Chapter 16. Universal error handling in React - [Example 1: try/catch inside useEffect](https://www.advanced-react.com/examples/16/01): Wrapping useEffect with try/catch never catches its errors because effects run after render, so the try/catch must be placed inside the effect instead. - [Example 2: Errors in children components](https://www.advanced-react.com/examples/16/02): A try/catch around a child element cannot catch errors inside it, since rendering an element only creates a definition that React executes later, after the block runs. - [Example 3: State updates during render](https://www.advanced-react.com/examples/16/03): Calling setState inside a catch block during render triggers an infinite re-render loop, showing why errors caught at render time cannot be handled with state. - [Example 4: Reusable ErrorBoundary component](https://www.advanced-react.com/examples/16/04): A class component with getDerivedStateFromError and componentDidCatch catches render errors anywhere below it, renders a fallback prop, and logs the error. - [Example 5: Re-throwing async errors](https://www.advanced-react.com/examples/16/05): Catching an async error with try/catch then re-throwing it inside a setState updater function pushes it back into the render lifecycle so ErrorBoundary catches it. - [Example 6: useThrowAsyncError hook](https://www.advanced-react.com/examples/16/06): Abstracting the re-throw trick into a hook gives an error thrower and a callback wrapper, letting one ErrorBoundary catch errors from promises and event handlers.