Table Of ContentWith Suspense and Concurrent Mode
John Larsen
M A N N I N G
React Hooks
in Action
WITH SUSPENSE AND CONCURRENT MODE
JOHN LARSEN
MANNING
SHELTER ISLAND
For online information and ordering of this and other Manning books, please visit
www.manning.com. The publisher offers discounts on this book when ordered in quantity.
For more information, please contact
Special Sales Department
Manning Publications Co.
20 Baldwin Road
PO Box 761
Shelter Island, NY 11964
Email: orders@manning.com
©2021 by Manning Publications Co. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in
any form or by means electronic, mechanical, photocopying, or otherwise, without prior written
permission of the publisher.
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in the book, and Manning Publications
was aware of a trademark claim, the designations have been printed in initial caps or all caps.
Recognizing the importance of preserving what has been written, it is Manning’s policy to have
the books we publish printed on acid-free paper, and we exert our best efforts to that end.
Recognizing also our responsibility to conserve the resources of our planet, Manning books
are printed on paper that is at least 15 percent recycled and processed without the use of
elemental chlorine.
Development editor: Helen Stergius
Technical development editor: John Guthrie
Manning Publications Co. Review editor: Aleksandar Dragosavljevic´
20 Baldwin Road Production editor: Deirdre S. Hiam
PO Box 761 Copy editor: Sharon Wilkey
Shelter Island, NY 11964 Proofreader: Keri Hales
Technical proofreader: Clive Harber
Typesetter: Dennis Dalinnik
Cover designer: Marija Tudor
ISBN: 9781617297632
Printed in the United States of America
To Mum, for all the books. And to Dad, for all the gadgets.
contents
preface xi
acknowledgments xiii
about this book xiv
about the author xviii
about the cover illustration xix
PART 1 ........................................................................ 1
1 React is evolving 3
1.1 What is React? 3
Building a UI from components 4 ■ Synchronizing state
and UI 6 ■ Understanding component types 10
1.2 What’s new in React? 12
1.3 React Hooks can add state to function components 13
Stateful function components: Less code, better organization 14
Custom hooks: Easier code reuse 17 ■ Third-party hooks provide
ready-made, well-tested functionality 18
1.4 Better UX with Concurrent Mode and Suspense 21
Concurrent Mode 22 ■ Suspense 23
1.5 React’s new publication channels 24
v
vi CONTENTS
1.6 Whom is this book for? 25
1.7 Getting started 25
2 Managing component state with the useState hook 27
2.1 Setting up the bookings manager app 28
Generating the app skeleton with create-react-app 30 ■ Editing the
four key files 31 ■ Adding a database file for the application 36
Creating page components and a UserPicker.js file 37
2.2 Storing, using, and setting values with useState 38
Assigning new values to variables doesn’t update the UI 39
Calling useState returns a value and an updater function 42
Calling the updater function replaces the previous state value 46
Passing a function to useState as the initial value 49 ■ Using the
previous state when setting the new state 50
2.3 Calling useState multiple times to work with multiple
values 53
Using a drop-down list to set state 53 ■ Using a check box
to set state 56
2.4 Reviewing some function component concepts 60
3 Managing component state with the useReducer hook 65
3.1 Updating multiple state values in response
to a single event 66
Taking users out of the movie with unpredictable state changes 66
Keeping users in the movie with predictable state changes 68
3.2 Managing more complicated state with useReducer 70
Updating state using a reducer with a predefined set of actions 71
Building a reducer for the BookablesList component 73
Accessing component state and dispatching actions with
useReducer 76
3.3 Generating the initial state with a function 79
Introducing the WeekPicker component 81 ■ Creating utility
functions to work with dates and weeks 82 ■ Building the reducer
to manage dates for the component 83 ■ Passing an initialization
function to the useReducer hook 84 ■ Updating BookingsPage to
use WeekPicker 85
3.4 Reviewing some useReducer concepts 86
CONTENTS vii
4 Working with side effects 92
4.1 Exploring the useEffect API with simple examples 93
Running side effects after every render 93 ■ Running an effect only
when a component mounts 95 ■ Cleaning up side effects by
returning a function 97 ■ Controlling when an effect runs by
specifying dependencies 99 ■ Summarizing the ways to call the
useEffect hook 103 ■ Calling useLayoutEffect to run an effect
before the browser repaints 103
4.2 Fetching data 104
Creating the new db.json file 104 ■ Setting up a JSON
server 105 ■ Fetching data within a useEffect hook 106
Working with async and await 108
4.3 Fetching data for the BookablesList component 109
Examining the data-loading process 110 ■ Updating the reducer
to manage loading and error states 111 ■ Creating a helper
function to load data 113 ■ Loading the bookables 114
5 Managing component state with the useRef hook 118
5.1 Updating state without causing a re-render 119
Comparing useState and useRef when updating state values 119
Calling useRef 121
5.2 Storing timer IDs with a ref 122
5.3 Keeping references to DOM elements 125
Setting focus on an element in response to an event 126
Managing a text box via a ref 129
6 Managing application state 134
6.1 Passing shared state to child components 135
Passing state from a parent by setting props on the children 136
Receiving state from a parent as a prop 136 ■ Receiving an
updater function from a parent as a prop 138
6.2 Breaking components into smaller pieces 140
Seeing components as part of a bigger app 141 ■ Organizing
multiple components within a page’s UI 142 ■ Creating a
BookableDetails component 143
6.3 Sharing the state and dispatch function from
useReducer 146
Managing state in the BookablesView component 147 ■ Removing
an action from the reducer 148 ■ Receiving state and dispatch in
the BookablesList component 148
viii CONTENTS
6.4 Sharing the state value and updater function from
useState 151
Managing the selected bookable in the BookablesView component 152
Receiving the bookable and updater function in BookablesList 153
6.5 Passing functions to useCallback to avoid redefining them 159
Depending on functions we pass in as props 159 ■ Maintaining
function identity with the useCallback hook 161
7 Managing performance with useMemo 164
7.1 Breaking the cook’s heart by calling, “O, shortcake!” 165
Generating anagrams with an expensive algorithm 166
Avoiding redundant function calls 169
7.2 Memoizing expensive function calls with useMemo 170
7.3 Organizing the components on the Bookings page 171
Managing the selected bookable with useState 173 ■ Managing the
selected week and booking with useReducer and useState 173
7.4 Efficiently building the bookings grid with useMemo 176
Generating a grid of sessions and dates 177 ■ Generating a lookup for
bookings 180 ■ Providing a getBookings data-loading function 182
Creating the BookingsGrid component and calling useMemo 182
Coping with racing responses when fetching data in useEffect 186
8 Managing state with the Context API 194
8.1 Needing state from higher up the component tree 195
Displaying a call-to-action message when the page first loads 196
Displaying booking information when a visitor selects a booking 198
Displaying an edit button for a user’s bookings: The problem 199
Displaying an edit button for a user’s bookings: The solution 200
8.2 Working with custom providers and multiple
contexts 206
Setting an object as the context provider’s value 206 ■ Moving
the state to a custom provider 207 ■ Working with multiple
contexts 213 ■ Specifying a default value for a context 216
9 Creating your own hooks 218
9.1 Extracting functionality into custom hooks 220
Recognizing functionality that could be shared 223 ■ Defining
custom hooks outside your components 224 ■ Calling custom
hooks from custom hooks 225
CONTENTS ix
9.2 Following the Rules of Hooks 227
Call hooks only at the top level 228 ■ Call hooks only from React
functions 228 ■ Using an ESLint plugin for the rules of hooks 229
9.3 Extracting further examples of custom hooks 229
Accessing window dimensions with a useWindowSize hook 229
Getting and setting values with a useLocalStorage hook 231
9.4 Consuming a context value with a custom hook 233
9.5 Encapsulating data fetching with a custom hook 235
Creating the useFetch hook 236 ■ Using the data, status, and error
values the useFetch hook returns 237 ■ Creating a more specialized
data-fetching hook: useBookings 238
10 Using third-party hooks 245
10.1 Accessing state in the URL with React Router 246
Setting up routes to enable nesting 248 ■ Adding nested routes
to the Bookables page 249 ■ Accessing URL parameters with the
useParams hook 250 ■ Navigating with the useNavigate hook 252
10.2 Getting and setting query string search parameters 256
Getting search parameters from the query string 258 ■ Setting the
query string 262
10.3 Streamlining data-fetching with React Query 266
Introducing React Query 267 ■ Giving components access to a
React Query client 269 ■ Fetching data with useQuery 270
Accessing data in the query cache 273 ■ Updating server state
with useMutation 276
PART 2 .....................................................................281
11 Code splitting with Suspense 283
11.1 Importing code dynamically with the import
function 284
Setting up a web page to load JavaScript when a button
is clicked 284 ■ Using default and named exports 285
Using static imports to load JavaScript 286 ■ Calling the
import function to dynamically load JavaScript 287
11.2 Importing components dynamically with lazy and
Suspense 288
Converting a component to a lazy component with the lazy
function 289 ■ Specifying fallback content with the Suspense