Tutorials on React Hooks

Learn about React Hooks from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

How to Use useCallback Hook with TypeScript

The useCallback hook returns a memoized callback that only changes if one of the dependencies has changed. This helps us to avoid unwanted and unnecessary components re-renders. The basic syntax for the useCallback hook is: You don't need any additional typings since TypeScript knows that useCallback accepts a function and an array of dependencies. It is preferable to use eslint-plugin-react-hooks though, to ensure you don't miss any argument in the dependencies array but that's optional. Let's assume we have a login form component: And then we have 2 input components: The problem is that when we change an email React will re-render both inputs instead of only EmailInput . This is happening because handler functions are being created on every re-render of the LoginForm component. So, on each render there are new handler functions for the InputEmail and PasswordEmail component, that's why they re-render each time. Let's fix that! Now, when we change an email or a password only the corresponding input component re-renders.

Fullstack React with TypeScript Masterclass is LIVE 🎉

The Fullstack React with TypeScript Masterclass is now live! 🎉   This Masterclass teaches you practical React and TypeScript for developing apps from idea to completion, along with all the important tools in the React ecosystem. It expands on the material taught in our comprehensive book,  Fullstack React with TypeScript , and gives you over 10 hours of video lessons taught by Maksim Ivanov. By the end of the first module, you'll already have created your environment for React with TypeScript, and you will have completed basic tasks with TypeScript. The subsequent modules then continue your journey through building multiple apps and learning techniques including: This masterclass was developed by Maksim Ivanov and Alex Bespoyasov and taught by Maksim. Maksim worked for leading game developer Mojang, where he helped develop front-end interfaces with React and TypeScript. He has continued his front-end work at Spotify, where he develops interfaces with React, TypeScript, and related tools.  Alex is a frontend developer and works with technology company 0+X where he consults on developing and maintaining applications with React and related tooling.  With their combined depth of expertise, Maksim and Alex will quickly get you up to speed on creating modern React and TypeScript apps that your users will love. You can read more details about the Masterclass over at the Fullstack React with TypeScript Masterclass page .

Thumbnail Image of Tutorial Fullstack React with TypeScript Masterclass is LIVE 🎉

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

useContext Hook - A Primer

Managing state in large React applications is difficult. Determining what state belongs locally to a component, what data a component receives from props, how much logic needs to be decoupled from a component, etc. directly affects an application's maintainability. One issue most developers face when developing a React application is prop drilling . Sending data down an entire component tree just to reach a single component is unnecessary, especially if none of the intermediate components need this data. With context , we can share global data (e.g., theme, time zone, i18n locale and user authentication status) with any component within the component tree without repeatedly passing data down as props. To understand why context is important, we must first understand the kinds of problems brought about by prop drilling. Consider the following barebones React application that comes with i18n support and allows users to select a preferred language. For instance, within the footer, switching the language from "English" to "Español" translates the application's text from English to Spanish. Note : For production-grade React applications, please use a dedicated i18n library like react-i18next for internationalization. Try it out in this CodeSandbox demo here . When you look at the <Layout /> component, you will notice that the props translate , changeLocale and locale are not used by this component whatsoever. Its sole purpose is to pass these props from the <App /> parent component to the <Navbar /> and <Footer /> child components. Two of the <Layout /> component's props, changeLocale and locale , are only needed for the <Footer /> component. If we decide to remove the <Footer /> component from the <Layout /> component, then we would have to make modifications to: And for larger applications, even more components would have to be refactored before you're able to successfully remove/add a single component. With the same problem also arising with the translate prop, which the <Layout /> component has no use for besides just passing it straight down the component hierarchy, taking the context approach directly exposes these methods to lower-level components like the <Footer /> component without introducing more bloat to intermediate components (in this case, the <Layout /> component). To demonstrate this, let's rewrite the application with context: Try it out in this CodeSandbox demo here . The first step to using context is to create a Context object with the createContext() method: This method accepts a single argument: the default data to share with consumer components if no matching provider component is found. Often, this data is replaced within the component responsible for rendering the provider component. Therefore, the main purpose of passing this data to the createContext() method is to: Every Context object provides the following: Within the render() method of the <App /> component, we have the I18nContext 's provider component, <I18nContext.Provider /> , wrap the entire application so that any child component with an <I18nContext.Consumer /> consumer component, such as <Footer /> , can access the currently selected language ( locale ) and methods for translating text ( translate ) and changing the language ( changeLocale ). Here, the context's default value gets replaced by the <App /> component's state object, which has the same properties. The only difference is that the translate and changeLocale methods interact with the <App /> component's state and actually do as they are named. With the <Layout /> , <Home /> and <Login /> components no longer receiving any props, the <App /> component's render() method becomes much cleaner and easier to reason about. Plus, we no longer have to track these props in the component hierarchy. Although the <Footer /> component is now tightly coupled to the I18nContext , if we decide to remove the <Footer /> component, then we could without making any additional modifications to other parts of the application. Taking a look at the <Footer /> component, changeLocale and locale come from the <I18nContext.Consumer /> consumer component's render props, not from the <Footer /> component's props. With changeLocale and locale only made available in the component's rendering logic, this render props pattern prevents us from defining functions (that rely on these values, such as event handlers) outside of the rendering logic. So for the (evt) => changeLocale(evt.target.value) callback passed to the <select /> element's onChange , when locale changes, a different callback gets created upon each re-render. This isn't problematic for the example above, but for callbacks passed as a prop to lower-level components, it causes extra re-renders. For function components, the useContext Hook simplifies how components consume and update data from a context provider. Let's see this in action by rewriting the application with function components calling the useContext Hook: Try it out in this CodeSandbox demo here . Creating the Context object and wrapping the entire application within the context's provider component remains the same as before. Instead of wrapping each component with a I18nContext.Consumer component, we can call a useContext Hook within the component's function body. This way, we eliminate the extra <I18nContext.Consumer /> wrapper components from the component hierarchy. Plus, we can access the context value anywhere within the component's function body, including functions defined within it and the useEffect callback. In the <Footer /> component, we can define the event handler, which calls the context's changeLocale method, outside of the rendering logic, like so: The useContext Hook accepts a single argument: a Context object (returned by the createContext() method). It returns the current context value for that specific Context. Anytime the provider's context value changes, any component subscribed to this context via useContext will re-render upon those changes. Note : If you have multiple components subscribed to the same provider, and one of those components updates the provider's value, then every one of these components will re-render upon that update. Therefore, you may want to use the useMemo Hook to avoid unnecessary, expensive re-renders. Since React's Context API serves as a state management solution for a React application's global state, most developers believe that they can substitute a library like Redux for the Context API. However, the Context API is not a one-to-one replacement for Redux. Using Context, we define the global state within a component and supply that state to the context's provider component's value prop. But with Redux, we define the global state outside of the component hierarchy within a centralized store, which holds this state. Compared to Redux, Context requires a lot less setup (no actions, reducers, etc.), but can be difficult to debug in applications with lots of deeply nested components. To learn more about the useContext Hook, check out the fifth YouTube tutorial in the six-part series on React Hooks by Paige Niedringhaus, a Blues Wireless Staff Software Engineer and author of The newline Guide to Modernizing an Enterprise React App .

Thumbnail Image of Tutorial useContext Hook - A Primer

The useRef Hook and How To Use It Safely - React Hooks 101 Series Part 4 of 6

We are continuing the tutorial series on React Hooks . Join Paige in today's tutorial as she teaches you all about the useRef hook, how it works, and how to use it in your own React apps. React refs help you imperatively modify the DOM outside the normal flow of component rendering. Here are some example scenarios: Since refs have often been thought of as an escape hatch that indicates that state should be managed elsewhere in the component hierarchy, there are a lot of questions about how to use them correctly. In this detailed but beginner-friendly guide, Paige goes over the nuances of using refs and the useRef React Hook properly so that you can confidently manage DOM elements directly in React. Get started with the useRef hook tutorial here. Up next in our tutorial series, Paige has more on how to use React's built-in Hooks, and how to create your own.

Thumbnail Image of Tutorial The useRef Hook and How To Use It Safely - React Hooks 101 Series Part 4 of 6

React Hooks 101 - Part 3: The useEffect Hook And How To Use It In Your Apps

We have the third tutorial in our 6 part YouTube series on React Hooks. (ICYMI - You can check out Part 1 - Introducing Hooks and Part 2 - useState Hook ). Now we're on to the useEffect hook, an incredibly useful hook that allows you to handle side effects such as API calls or modifying the DOM in your function components. The useEffect Hook performs side-effects in function components. The term "side-effects" refers to actions that cause things to occur outside the scope of the function being executed. This includes sending requests to an API, logging, modifying the DOM, subscribing to event listeners, etc. Behavior-wise, you can think of the useEffect Hook as the componentDidMount , componentDidUpdate , and componentWillUnmount lifecycle methods you'd use in class-based components, neatly packaged into one Hook. Follow along as Paige teaches you this second of the most important React Hooks you should know. Your instructor for the tutorial is Paige Niedringhaus, a Staff Software Engineer at Blues Wireless, host of the React Roundup Podcast, and instructor of newline's course: The newline Guide to Modernizing an Enterprise React App . In the full course, Paige covers: If you want to dive deeper into React and master the best practices for modernizing a React app, check out Paige's full course over at  The newline Guide to Modernizing an Enterprise React App .  Stay tuned for parts 4, 5 and 6 in our React Hooks 101 series coming soon!

Thumbnail Image of Tutorial React Hooks 101 - Part 3: The useEffect Hook And How To Use It In Your Apps

React Hooks 101 - Part 2: The useState Hook and State Management in Function Components

Here is the second tutorial in our 6 part YouTube series on React Hooks. We've already seen that React Hooks are arguably the biggest fundamental change to happen to React since its inception. Learning Hooks brings you up to speed with this important update to React. Now in this second tutorial, we will teach you the ins and outs of using the useState hook, the most commonly used React Hook, and thus, one of the most important ones you should know. You will see that state management using the useState hook is in many cases more straightforward than using class-based components. Function components have come a long way since React v0.14. Introduced as a simpler syntax for defining stateless, presentational components, function components can now handle state via the useState Hook. This means you can define any component, stateful or stateless, with functions, and you no longer have to deal with the verbose code that comes with classes. Using the useState hook, you can keep track of state changes as the user interacts with your functional components, much as you could do with class-based components. Your instructor for the tutorial is Paige Niedringhaus, who's a Staff Software Engineer at Blues Wireless, and an expert at React as well as related frontend technologies. Paige has a depth of experience in software development with large organizations, including at The Home Depot, where she spent 5 years in engineering. In this part 2/6 React Hooks tutorial, she covers: Mastering the contents of this free tutorial gets you ready to use the most commonly used React Hook and understand React code that uses it. Get started with the tutorial here. And watch for the continuation of the series, when we move into the other hooks you'll use most frequently on React projects. If you want to dive deeper into React and master the best practices for modernizing any React app, then check out Paige's full course: The newline Guide to Modernizing an Enterprise React App . This course covers it all: React Hooks, Design Systems, Testing, and best practices for modern React.

Thumbnail Image of Tutorial React Hooks 101 - Part 2: The useState Hook and State Management in Function Components

useState - A Primer

Function components have come a long way since React v0.14. Introduced as a simpler syntax for defining stateless, presentational components, function components can now handle state via the useState Hook. This means you can define any component, stateful or stateless, with functions, and you no longer have to deal with the extra, unnecessary code that comes with classes. In fact, if you choose to write all your components as function components, then the bundle size of your React application significantly decreases. To understand how the useState Hook lets you manage state in function components, we must first revisit class components. When you create a class component, all of the component's state is stored within a single object. Within a class constructor, this object gets assigned to the component's state instance property, like so: To update a single value (or multiple values) of the component's state, call the component's setState() method: Try it out in a CodeSandbox demo here . With the useState Hook, you no longer have to define stateful components with the class syntax. Here's how you define the <App /> class component as a function component: Try it out in a CodeSandbox demo here . Notice how much smaller the component's definition has become. Anytime you write a class component, you end up repeating the same boilerplate code: The useState Hook is a special function that lets you add state to function components. When called, this Hook returns a state variable and a function for updating the state variable's value. The state variable contains the current state. The useState Hook accepts only one argument: the initial state. initialValueOfStateVariable can be anything: a string, a number, an object, etc. Conventionally, you unpack the state variable and update function from the array returned by the useState Hook. Additionally, you name the update function after the state variable, but prefixed with the word set . For a state variable named isMessageShown , its corresponding update function should be named setIsMessageShown . The update function behaves similarly to the setState method: However, there is a key difference between the two. While the setState method shallowly merges the component's new state with its old (most recent) state, the update function completely replaces the old state with the new state. For example, given an initial state of... Calling... Leaves user and count intact, but only changes the value of isMessageShown . The current state becomes a new object that contains the modified isMessageShown and the original user and count : Try it out in a CodeSandbox demo here . Note : For state with deeply nested objects, you may want to use the spread operator to preserve the nested values. On the other hand, the update function completely wipes out user and count and only keeps the modified isMessageShown in the new state: Try it out in a CodeSandbox demo here . As a best practice, you should... To learn more about the useState Hook, check out the second tutorial in the six-part YouTube series on React Hooks by Paige Niedringhaus, a Blues Wireless Staff Software Engineer and author of The newline Guide to Modernizing an Enterprise React App.

Thumbnail Image of Tutorial useState - A Primer

Testing a Custom React Hook (useMap)

Developers of the most popular React Hooks libraries rely on tests to enforce the overall quality of their libraries' code. Tests cover a wide variety of different use cases, give developers confidence that everything works as intended and serve as a form of documentation. Anytime a test fails, developers know which set of arguments to use to replicate the bug encountered and squash it lands in the distribution package. When writing a custom React Hook for a library, the Hook should be tested regularly and against the fringest of edge cases to appeal to a greater number of projects. Setting up a testing environment that executes tests fast and reliably requires the proper tools: This testing environment allows you to write tests that closely resemble your user's actions. For example, @testing-library/react comes with methods for rendering a React component ( render ) to a container ( document.body by default) and finding an element within the rendered content of this container via the element's label ( screen.getByLabelText ): With just these two methods, our test mimics, at a high-level, the browser rendering a contact form to the screen and the user searching for an e-mail address input field. In the case of React Hooks, you may not want to create dummy components for the sole purpose of testing your Hooks. A unit test for a React Hook should only test the Hook's functionality (independent of any component calling it). We should reserve the testing of Hooks called within a component for integration tests. Fortunately, the @testing-library/react-hooks library gives us testing utilities for testing Hooks in isolation without having to render any dummy components. Below, I'm going to show you how to test a custom React Hook built for a React Hooks library with the @testing-library/react-hooks library and Jest. To get started, clone this React Hooks library template from GitHub: This template has ESLint, TypeScript and Jest already configured and comes with a custom React Hook, useMap , which we will write tests for. Additionally, the @testing-library/react-hooks library has already been installed as a dev. dependency. The useMap Hook wraps around a Map object and mimics its API. If you would like to learn how to implement this Hook from scratch, then check out the blog post here . Within the __tests__ directory, create a new file, useMap.test.ts . We will write unit tests for the useMap Hook within this file. Within this file, import two methods from the @testing-library/react-hooks library: Then, import the useMap Hook. ( __tests__/useMap.test.ts ) Add a describe block with the text "useMap" to group all tests related to the useMap Hook within this one describe block. ( __tests__/useMap.test.ts ) Alongside the map state variable, which represents the Hook's current Map object, the useMap Hook provides several action methods for updating this state variable: From this point on, all describe blocks and tests will be written within the useMap describe block. Let's write a describe block for the set action method that covers two cases involving this action method: ( __tests__/useMap.test.ts ) For the "should update an existing key-value pair," we should render the useMap Hook using the renderHook utility method from the @testing-library/react-hooks library: ( __tests__/useMap.test.ts ) Here, we call the Hook with an array of one key-value pair. We pass this to a new Map object to create the initial map . The renderHook method returns an object with a result field. This field is a React ref. By reading the ref's current field, you can access the Hook's API (an array that contains the map state variable and the action methods). For now, let's omit the map state variable. I will explain why later on. ( __tests__/useMap.test.ts ) Let's double-check that our initial state was set correctly to a Map object with the key-value pair 1: "default" . ( __tests__/useMap.test.ts ) Save the changes. In the terminal, run the test npm script to verify that the initial state is set correctly: Now, let's call the set action to update the key-value pair of 1: default to 1: changed . We need to call the set action within the act method to flush any changes to the state into the simulated DOM before running any subsequent assertions. ( __tests__/useMap.test.ts ) Check that the key-value pair has been updated. The 1 key should have a corresponding value of "changed" . ( __tests__/useMap.test.ts ) Once again, save the changes. Run the test npm script to verify that the state has correctly changed: ( __tests__/useMap.test.ts ) With these few steps, you can write tests for the remaining action methods: ( __tests__/useMap.test.ts ) Remember how we omitted the map state variable and only accessed it from result.current[0] ? This is because all action methods are immutable. Therefore, anytime we call any one of these action methods, the map state variable destructured from the initial result.current will reference the initial Map object it's set to, not the new Map object that set it to internally in the Hook. Essentially, after the action method call, result.current references a completely different Map object than the one referenced by the destructured map state variable. Let's add a new describe block labeled "hook optimizations." Inside of this describe block, write a test to confirm this behavior: ( __tests__/useMap.test.ts ) Finally, let's write a test to make sure our useCallback and useMemo optimizations maintain reference equality after state changes. The reference to the action methods should never change. ( __tests__/useMap.test.ts ) Run the tests one final time and watch them all pass! Altogether... ( __tests__/useMap.test.ts ) For a final version of this code, visit the GitHub repository here . Try testing your own custom React Hooks with the @testing-library/react-hooks library.

Thumbnail Image of Tutorial Testing a Custom React Hook (useMap)

Implementing a useMap React Hook

Ever since the introduction of Hooks into the React library, creating cleaner, reusable components has become much easier. Instead of using render props and higher-order components, Hooks provide us a way to share stateful logic across multiple components without making any modifications to an application's component hierarchy. React comes with several built-in Hooks for handling component state and lifecycle, such as useState and useEffect , that can be composed to create all kinds of different Hooks. Creating your own custom Hooks can be tricky. Once you decide upon the part of a component to extract out into a separate function as a custom Hook, you need to carefully refactor this stateful logic to... For example, a Hook that manages authentication should... Keeping the Hook simple, broad and flexible opens up the components that can use it. In this case, any component that depends on the user's authentication status, such as a navigation bar to determine whether or not to display a login button or a dropdown toggle, can call this Hook and have access to its state and methods, all with a single line. When done properly, you can even abstract your Hooks into a React Hooks library for other developers to use in their own applications (irrespective of business logic). Below, I'm going to show you how to implement a custom React hook, useMap , within a React Hooks library. The useMap Hook wraps around a Map object and mimics it's API. This allows your React components to leverage Map objects without having to worry about low-level details like try...catch error handling. To get started, clone this React Hooks library template from GitHub: This template has ESLint, TypeScript and Jest already configured so that we can write, lint, test and build the useMap Hook for distribution. Within the src directory, create a useMap.ts file, which will contain the source code of the useMap Hook. Unlike plain JavaScript objects, Map objects can set objects as keys. This is quite useful for situations like mapping DOM elements to a corresponding piece of data or functionality. Additionally, Map objects are iterable, and keys set on the Map object will not conflict with properties inherited from the Object prototype like toString and constructor . The useMap Hook's API will closely follow the original React Hooks API of returning a pair of values: the current state and action methods for updating it. The Hook will return a Map object as the state and the following action methods for interacting with this object: Each time we perform any of these actions on the Map object, we create a new instance of a Map object to make it immutable to change. Here's how a component would call this Hook: Note : In the above code, the Map object maps DOM elements to strings. Let's start by implementing the Hook's state and setValue action method: ( src/useMap.ts ) The Hook can be passed a Map object or an array of key-value pairs (entries) to initialize the keys and values of the map state variable. If nothing is passed to the Hook, then initialState is set to a new, empty Map object by default. Define the clear action method, which empties the Map object of its key-value pairs: ( src/useMap.ts ) Define the set action method, which adds a new key-value pair or replaces an existing key-value pair: ( src/useMap.ts ) Define the deleteByKey action method (publicly exposed as delete ), which deletes a key-value pair: ( src/useMap.ts ) Define the initialize action method, which initializes map to a new Map object based on a passed tuple (or other iterable object). ( src/useMap.ts ) If any of these action methods are passed to a child component via props, then anytime map changes and causes the calling parent component to re-render, this triggers a re-render of its child components even though none of these methods changed. To prevent this unnecessary re-render, we should wrap each action method with useCallback and memoize the actions object with useMemo , like so: ( src/useMap.ts ) Since the keys and values of the map state variable can be of any type, they should be generically typed . Let's denote the generics by the type variable <K, V> : K for a key and V for a value. This type variable preserves the type information of the key-value pairs. Let's make use of this type variable by defining a type MapOrEntries that describes... ( src/useMap.ts ) Rewrite the useMap function as a generic function and annotate the initialState and mapOrTuple parameters with this type, like so: ( src/useMap.ts ) Finally, we need to define a type for the array, consisting of the map state variable and the action methods, returned by the Hook. Name this type UseMap , and define it as the following: ( src/useMap.ts ) Now, define the UseMapActions type, which provides a type definition for each action method: ( src/useMap.ts ) The Dispatch type tells TypeScript that setValue is a function that returns nothing. This is perfectly valid because this method simply updates the map state variable. That's it. The SetStateAction type tells TypeScript that setValue can be passed either... Altogether... ( src/useMap.ts ) Don't forget to export the types and the Hook inside the src/index.ts file! ( src/index.ts ) For a final version of this Hook, visit the GitHub repository here . Try refactoring your custom React Hooks into a separate React Hooks library, and share them with other team members and/or developers.

The newline Guide to Modernizing an Enterprise React App is Now Live!🎉

Creating large, long-lived React apps, such as those required in large enterprises, poses unique challenges. Most developers lack the knowledge of how to build apps that scale gracefully and use the latest React techniques, such as React Hooks and React Testing Library, to modernize React apps in the enterprise. This course will help you master React development in the context of building for large enterprises. You will learn the latest React syntax, React Hooks, and more as you build an actual enterprise React app. You will learn: In  The newline Guide to Modernizing an Enterprise React App,  we teach you the various aspects of React development that ensure that apps vital to a company's success keep running. This is based on years of experience building and maintaining large-scale, complex, React apps in production, and will prepare you to do the same for any enterprise. By the end of the first module in the course, you'll already have started working with the sample enterprise React app, Hardware Handler, and preparing to modernize it using the latest React standards. The subsequent modules will teach you important React concepts and guide you in modernizing this React app, including: Paige Niedringhaus  is your instructor for this course. She's a Staff Software Engineer for the Internet Of Things startup, Blues Wireless, which has backing from leading investors, including Sequoia Capital and Microsoft founder Bill Gates. Paige has a strong background in React and large-scale enterprise apps, having worked in software engineering for The Home Depot for 5 years. Now she teaches you everything you need to build beautiful apps with React in a way that can support the mission-critical demands of large enterprises. You can read more details about the course over at the Modernizing An Enterprise React App website  

Thumbnail Image of Tutorial The newline Guide to Modernizing an Enterprise React App is Now Live!🎉

Writing a Custom React Hook for Spotify's Web API (Implicit Grant Flow)

As one of the most popular music streaming services, Spotify encourages developers to craft new and engaging experiences for music lovers around the world. With over seventy endpoints, Spotify's Web API allows external applications to access Spotify's vast catalog of albums, artists, playlists, tracks and podcasts and detailed profile information about the current authorized user. All of this data opens the door to building applications that explore and analyze the data, generate new insights from the data or present the data in exciting new ways. Want to discover new artists based on the artists of the tracks in your playlists? Use the GET https://api.spotify.com/v1/artists/{artist_id}/related-artists endpoint to fetch artists related to an artist based on the analysis of other users' listening histories. Want to re-imagine the user interface for searching and displaying tracks that match a query? Use the GET https://api.spotify.com/v1/search endpoint to query and retrieve results from Spotify's tracks catalog. If you decide to create a Spotify-connected application with React , then centralizing all Spotify-related logic inside of a single, reusable custom hook, named useSpotify , eases the integration of Spotify into the application. This organizes everything Spotify-related in one place. For a component to communicate with Spotify's Web API, just import the useSpotify hook and call the hook within the component. Whenever Spotify updates its API with new endpoints or modified response objects, you edit one single file in the codebase: useSpotify.js . The hook enables all components to get the authorization status of the user and interact with Spotify's Web API. Below, I'm going to show you... Imagine building a dashboard that features a view for searching tracks from Spotify's catalog, a view for managing the current authorized user's saved albums and tracks, etc. For the custom hook useSpotify to support this type of application, it must handle: To begin, let's briefly recap React hooks and how they work. Hooks provide us a way to reuse stateful logic. When multiple components use the same hook, the state within the hook is not shared by those components. Therefore, we will need a provider component to wrap the application and make the hook's object available to any child component that calls the hook with context. Anytime the user decides to "log in" or "log out" (represented as having or not having a valid access token respectively), the changes to the hook's state will cause those components to re-render. Here's the base template of the hook, which exports the provider component <SpotifyComponent /> and a hook that returns the current context value, which comes from the object passed to the value prop of the provider component. ( useSpotify.js ) All of the Spotify-related logic will reside within the useProvideSpotify provider hook, which creates the spotify object that's fed to the provider component, exposes methods for working with Spotify's Web API and manages state variables like token and user . To obtain authorization, the hook will implement methods for facilitating the Implicit Grant Flow . Although the Implicit Grant Flow does not provide a refresh token, it requires only the client-side application to carry out the entire authorization flow. No additional backend code needed! Upon being granted authorization, Spotify issues a short-lived access token that expire within 3600 seconds (1 hour). Once the token expires and is no longer valid, you must complete the entire flow again to obtain a new access token. To start, let's write a login method that opens a popup that prompts the user to... ( useSpotify.js ) Upon authorization, the user is redirected to the redirect URI (e.g. http://localhost:3000/callback ) within the popup. The redirect URI contains a hash fragment with the access token, its type, its expiration time period and state (e.g. http://localhost:3000/callback#access_token=xxxx&expires_in=3600&token_type=Bearer&state=xxxx ) encoded as a query string. When this page loads and its component is mounted, extract the access token and its metadata from the query string and store the token and its expiration timestamp in local storage. Then, call the main window's spotifyAuthCallback method, which was registered back in the login method, to close the popup and update the hook's state with these values. ( useSpotify.js ) By storing the token in local storage, we don't need to constantly ask the user to re-authorize themself if they decide to close the browser, reopen it and revisit the application less than an hour later. And, if the user does revisit the application more than an hour later, then knowing the expiration timestamp makes it possible to invalidate the token and ask agains for authorization. ( useSpotify.js ) Note : Any value stored in local storage is stringified and must be converted back to its appropriate typing. Note : Yes, it's not recommended to store access tokens in local storage due to cross-site scripting (XSS) and possibly being read by malicious JavaScript code. Only do this for demos. For production-grade applications, I recommend going with a different authorization flow (one that involves the server-side and setting the token within an HTTP-only cookie). Anytime the user decides to "log out," invalidate the token and reload the page so that it automatically redirects them to the homepage. ( useSpotify.js ) To restrict the redirect URL to only be visited within the popup by Spotify, let's write a method to check whether the redirect occurs within a "valid" popup that originated from the application itself. ( useSpotify.js ) The useHistory hook from react-router-dom gives a history instance to verify its length is at least two (one entry for Spotify, the other for the redirect). Once the token and expiration timestamp state variables are updated, the hook should automatically fetch the current authorized user's information from Spotify and update the state with this information. ( useSpotify.js ) For the user to be considered "logged in," the hook's state must the token and user's information, and the token cannot be expired. ( useSpotify.js ) To get data from Spotify's Web API, define a method for each endpoint. For this hook, we will only define two methods: one for the GET /me endpoint and another for the GET /search endpoint. Any request sent to the API must have the access token added to its Authorization header to allow Spotify to identify the user and know that the requesting application has permission from the user to access to their data. ( useSpotify.js ) The callEndpoint method serves as a helper method that keeps the endpoint methods' definitions DRY. For more endpoints, visit Spotify's Web API reference here . When the user performs a full-page refresh of the application, it takes time for the application to fetch the user's information. The hook should provide a flag that notifies components when the application is "loading" so that they can present a loading indicator to the user. The application is in a loading state when the hook is initialized, and it is finished loading when it has successfully (or unsuccessfully) fetched the user's information from Spotify. ( useSpotify.js ) The hook will expose the following state variables and methods to child components that call it: ( useSpotify.js ) Using getters allows the component to reference the method call like a flag. So instead of calling hasLoggedIn() , just use hasLoggedIn in the component. Altogether... ( spotify.js ) ( .env ) ( useSpotify.js ) Want to see how this hook works in an actual application? Clone the demo application here and run it locally. Try using this hook for your next Spotify-connected application!

Thumbnail Image of Tutorial Writing a Custom React Hook for Spotify's Web API (Implicit Grant Flow)

How to Test Your First React Hook Using Testing Library

In previous posts we learned: In this post, we're going to write tests for a custom React hook. We're going to create a custom hook that will uppercase a given text string. This hook will be connected to an input and whenever a user changes the input value this hook will automatically uppercase the value. Let's write the hook. Create a file called useUppercase.ts In this file, we create a custom hook function useUppercase() . It accepts a string as an initial argument. We transform this string using .toUpperCase() and then store the result value in a local state. Also, we create a function update() . This function will be a part of the public API. With this function, components will be able to update the current value. Finally, we use useEffect() to re-render the hook if the initialValue gets changed. This, for example, happens when the component gets new props and passes the new initial value to the hook. In this case, we need to update the local state with the new value from the component. Now, let's test the hook! To test hooks, we're going to use React Hooks Testing Library . It gives us utilities for testing hooks without even rendering a single component. Let's install it: Now, we create a file useUppercase.test.ts . In this file, we import our hook and describe our first test: The first thing we want to test is that the hook returns a given initial value in the upper case. With React Hooks Testing Library, we don't need to render a whole component, instead, we render the hook itself with a special function called renderHook() : The renderHook() function returns an object with the result field. We can access the current render result with the current field. It contains the object our hook returns. We can use autosuggestions to select a field to test against: The coolest feature is readability. We don't need to create extra infrastructure code to test hooks in isolation. It just works! Another thing we want to test is that when we call update with a new string, the hook's value updates. Let's write another test: The current render result contains a reference to our update() method, so we can use it to simulate a change. Notice that we need to use act() . It is required for the hook to update the values inside of it. According to the documentation : The last thing to cover is a case when the hook gets a new initialValue . In this case, we need to update its values and re-render the component that is using them. In this test, we access not only the result but also the rerender() method. This method renders the hook with another initial value. Also, this time we use props to pass initial values. They help us to keep the code shorter and more readable. In general, we pass the initialProps object to options of the render() method. When we need to re-render the hook, we can pass updated values for this object. The library infers the type of the object so we can use autosuggestions here as well:

Thumbnail Image of Tutorial How to Test Your First React Hook Using Testing Library

Vue 3 - The Composition API (Part 1)

As the most starred open source, JavaScript library/framework repository on GitHub, Vue.js has become a top three front-end technology alongside React.js and Angular in terms of popularity, usage, ecosystem activity and developer satisfaction. Compared to React.js and Angular, Vue.js is incrementally adoptable and provides a declarative API that resonates with AngularJS developers. Evan You , the author of Vue.js, explained the original concept of Vue.js as extracting the best parts of AngularJS, such as directives (i.e., v-if and v-show ), and building a lightweight, flexible alternative. Building large Vue.js applications requires composing components together with state management (i.e., Vuex ) and routing (i.e., Vue Router ) libraries. In September 2020, the Vue.js team officially released Vue 3, which welcomed a number of improvements and new features: Particularly, the Composition API of Vue 3 has been met with controversy due to its resemblance to React hooks and its philosophical divergence from the Options API , which emphasizes separation of concerns by defining component logic within specific options ( data , props , computed , methods , etc.). For those who prefer the Options API, unlike other major version upgrades that introduce incompatible changes, the Composition API will not break existing Vue components using Options API (" purely additive "). Although it offers similar logic composition capabilities as React hooks, the Composition API leverages Vue's reactivity system to circumvent several of React hooks' issues. To understand why the Composition API's new approach for creating components allows developers to better reason about and maintain large components, we will need to... A single file component consists of HTML-based markup ( <template /> ), CSS-based styles ( <style /> ) and JavaScript-based logic ( <script /> ), all self-contained within a single .vue file. Example : The following component will display "Hello World!" as red text. Note : The scoped attribute applies to CSS only to the elements within the current component. In the above example, the data function returns an object that represents the component's data. Vue converts each data property to a Proxy , which makes the state reactive by allowing for proper this bindings and tracking/triggering changes. The object returned by data contains a single property, greeting , which has a value of "Hello World!" and is rendered within the <p /> element's mustaches ( {{ ... }} ). For a one-time interpolation, use the v-once directive. Note : In previous versions of Vue, the reactivity system used Object.defineProperty , not Proxy . Now that you are familiar with the base structure of a component, let's explore a slightly more complex component. Open the CodeSandbox demo here . In this demo, let's look at a component that represents a simple accessible modal. When the modal is opened, the focus should be trapped within it. Elements within the modal should be "tabbable." When the modal is closed, the focus should return back to the element responsible for opening the modal. ( src/components/Modal.vue ) ( src/App.vue ) Here, the <Modal /> component is defined using the Options API , which organizes component logic into specific options. The initialization of internal state ( data ), the passed props ( props ), the emitted custom events ( emits ), the available instance methods ( methods ) and lifecycle hooks ( beforeMount , mounted and unmounted ) are clearly separated from one another. For an option to access values/methods defined within other options, those values/methods must be referenced via the this keyword, which refers to the component instance itself. Below is a list of commonly used options: Note : Do not use arrow functions when defining a watcher or methods / computed method. Otherwise, the this keyword will not reference the component instance. As a component grows larger with more new features, it increasingly becomes more difficult to maintain and reason about the component, especially when the logic of each feature is fragmented over the individual options. The RFC for the Composition API provides a side-by-side comparison of how logic related to a feature (also called a logical concern in the official documentation ) is distributed throughout a component's code. Each logical concern is identified by a unique color. Notice how neatly grouped each feature's logic is when using the Composition API. By restricting component logic to specific options, it adds a mental tax by requiring us to constantly switch from one block of code to another to understand/work on any single feature of a component. Also, it limits our ability to extract and reuse common logic between components. This is the primary motivation behind the Composition API. By exposing Vue's core capabilities, such as reactivity and lifecycle hooks, as standalone functions, the Composition API can use these functions within the setup component option, which is executed before the component is created (formerly the created lifecycle hook option) and serves as the component's main entry point. Let's revisit the simple accessible modal, but this time, create the component using the Composition API. Open the CodeSandbox demo here . ( src/components/Modal.vue ) ( src/App.vue ) All of the logic that was previously handled in multiple options of a Vue component is now contained within a single option, setup . Functions that behave similar to those options can be imported as named exports from vue and called anywhere within the setup function. For example, the lifecycle hook options beforeMount , mounted and unmounted can be replaced using the onBeforeMount , onMounted and onUnmounted methods in setup respectively. This allows component logic to be structured and arranged flexibly. The reactive data returned by the data option can be replaced using the ref and reactive methods in setup . The ref method accepts a default value and returns a reactive ref object that can be safely passed throughout the entire application. Because this object is mutable, the value can be directly modified. To reference this value, access this object's .value property. ref is commonly used for establishing reactivity for a single primitive value. To establish reactivity for an entire object, use the reactive method. setup exposes two arguments, props and context . props contains the props passed from a parent component. They are reactive and automatically updated whenever new props are passed in. To properly destructure props , which means still preserving each props reactivity after destructuring, use the toRefs method. context contains three properties: Within the context of the <Modal /> component: Although the component's methods are defined within the setup option, the component's template can only access these methods when they placed within the object returned by setup . This also applies to ref and reactive values, which are automatically unwrapped to allow the template to access their values without having to reference .value . The close method and modalRef ref are made available to the <Modal /> template. The close method is set to the @click shortcut directive, so when the user clicks this button, the "close" event will be emitted by the component, which will trigger the function set to @close on the <Modal /> component within the <App /> parent component (the closeModal method). When set to the <div class="model" /> element's ref , modalRef will reference this DOM element. A component built with the Composition API has its setup function only called once during its entire lifetime, regardless of how many times it is re-rendered. A React functional component using hooks is called whenever a re-render occurs as a result of a state/prop change, which pressures the browser's garbage collector. React provides useCallback to prevent inline functions in functional components from being garbage collected on subsequent re-renders via a referential equality check. Additionally, these re-renders may cause unnecessary re-renders, which happens when the function representing a child functional component is called when its parent component is re-rendered, even if it is completely stateless. Example : When the count increases/decreases upon clicking any one of the <Counter /> component's button, the Child function is called. However, its DOM is unaffected by this state change. This is an unnecessary re-render. If this component was larger with more inline handlers, calls to hooks, etc., then any unnecessary re-render would cause these inline handlers, etc. to be garbage collected. React provides a number of memoization-related methods ( useMemo , memo , etc.) to address this. Of course, you should use your browser's profiling tool first to identify your application's actual bottlenecks before chucking in useMemo , memo and other memoization techniques. Each developer reasons about code differently. Whether you find it easier to reason about code by its low-level (Options API, which is better suited for grouping logic by a low-level attributes of a component) or high-level (Composition API, which is better suited for grouping logic by a component's high-level features) implementation, you must always evaluate and make trade-offs that best serves your needs. You should definitely read this RFC that outlines the Vue team's rationale and decisions for the Composition API, along with addressing some of the common criticisms echoed within the Vue community. Many of these new features, such as portals and fragments, in Vue 3 are already present in React v16+. Try converting your React functional components to Vue 3 components using the Composition API. Please read Part 2 of this blog post to learn about the main benefit of the Composition API: the capability to extract and reuse shared logic . If you want to learn more about Vue 3, then check out Fullstack Vue :

Thumbnail Image of Tutorial Vue 3 - The Composition API (Part 1)

How to Use react-hook-form with TypeScript

React Hook Form is a library that helps you to simplify form validation. It uses React hooks to inject required validation checks and to bind a form and a submit handler. Let's create a signup form with React Hook Form and then type it with TypeScript. Out form will contain 3 fields: To connect the form with validation checks we will use useForm hook from the React Hook Form API: Here, we use register as a value to ref prop on each input. It binds the input with validation. We need to pass the name attribute as well since register relies on it. Also, the name must be unique for register to work properly. The handleSubmit function will call the provided callback if validation is successful. In our case, it will call onSubmit callback and log out all the data from the form. Now let's create a type for form data. Let's call it User : When type is created we can use it to annotate the form data: To make an input required, we can provide register with a settings object. When we specify the required field as true , the validation returns an errors object. We can use this object to access errors on every field in the form: We can also specify a required pattern for each field to perform custom checks:

Handling File Fields using React Hook Form

In this article, we will learn how to handle file uploads using react-hook-form.react-hook-form is a great library that provides an easy way to build forms with React. It provides a number of hooks that simplify the process of defining and validating various types of form fields. In the following sections, we will learn how to define a file input, and use it to upload files to firebase. We will use create-react-app to generate a stock React app. We'll call our app react-hook-form-file-input . Once the app is ready, we can navigate into the folder and install react-hook-form . Let us define our form in the app.js file. We can remove all the default markup added by create-react-app , and add a form element which contains a file input and a submit button like so: We can now connect our form element to react-hook-form using the useForm hook. useForm returns an object containing a register function which, as the name suggests, connects a given element with react-hook-form . We need to pass the register function as a ref into each element we want to connect. Now that our file input has been registered, we can handle submissions by adding an onSubmit handler to the form. The useForm hook also returns a handleSubmit function with which we will wrap our onSubmit handler. The data parameter that is passed to onSubmit is an object whose keys are the names of the fields, and values are the values of the respective fields. In our case, data will have just one key - picture , whose value will be a FileList . When we fire up the app using yarn start , we will see this on screen. On choosing a file and clicking 'Submit', details about the uploaded file will be logged to the console. Now that we have learnt how to work with file inputs using react-hook-form , let us look at a slightly more advanced use case for uploading files to Firebase . You can find the code for the Firebase file upload example here . Clone the repo and run yarn to install the dependencies. You can set up your Firebase configuration in the .firebaserc and firebase.json files at the root of the project, and log into Firebase using the CLI . As we've seen earlier, we can install react-hook-form via yarn using: The App.js file contains a file input which uploads a file to Firebase. We can now switch it over to use react-hook-form like so: We have wrapped the input element with a form , given it a name and registered it with react-hook-form . We have also moved all the logic in the onChange event handler into our onSubmit handler which receives the data from react-hook-form . We can run the app using the yarn start command and it will look the same as earlier. Choosing a file and clicking 'Submit' will upload it to Firebase. We have now learnt how to work with file inputs using react-hook-form . ✅ The code used in this article is available at https://github.com/satansdeer/react-hook-form-file-input and https://github.com/satansdeer/firebase-file-upload .

Thumbnail Image of Tutorial Handling File Fields using React Hook Form

How to Handle Effects Using Hooks in React with TypeScript

There are 2 hooks to handle side-effects in React: The first one fires after layout and paint, during a deferred event. The second one works synchronously before the next paint, and used to handle effects that are visible to a user. The useEffect hook accepts 2 arguments: By default, useEffect fires on every re-render. If you need it to fire only when certain values change use the second argument to point out those values. You can also return from an effect a clean-up function. The clean-up function runs before the component is removed from the UI to prevent memory leaks. You don't need any additional typings for the useEffect hook. However, TypeScript knows about its inner structure and type signatures, so there is no chance to compile something like: This hook is the same in a sense of type signatures as the useEffect hook. So you can re-write a counter component using it: It also doesn't require any additional typings.

How to Use useReducer with TypeScript

The useReducer hook is a hook that allows you to create a state, update it, and share its data across different components. (Its core logic is similar to Redux .) It takes a reducer-function and an initial state as arguments and returns a tuple of a new state and a dispatch function. The reducer must extend the Reducer<State, Action> type, which is a function that takes a state and an action as arguments, updates the state, and returns the updated state: A state is usually an object with some data. Let's use a counter as an example. If we want to keep track of a current counter value, we can create an object with a value field: We will use this State type as a type parameter for the Reducer type later, and the initialState object will be the default value for the state. An action is sort of like an event, which triggers the state updates. For example, a counter can have 2 actions: for increasing and decreasing its value. Usually, an action is an object that has a type and payload . The type is like an ID of this action, and a payload is a data that the action transfers. Now that we have a state and a set of actions we can create a reducer. When a reducer is ready, we can use the useReducer hook. Now we combine our initial state, reducer, and actions with a component:

How to Use React Refs with TypeScript

Refs provide a way to access DOM nodes or React elements created in the render method. Also, they can be used to store some references to entities or objects for accessing them later. To use refs with functional components use a special useRef hook . It is a generic function, so we can pass a type-parameter, that will tell TypeScript what type is acceptable for this ref. Initially, we set a ref's value as null , because it will be set later on render. That's why we need to null-check inputRef.current later in onFocus . Also, inputRef itself is an object that contains a value in the current field. So to access the real element we need to get a value of this field. In class components, you can store refs in private class fields after creating them with createRef . When you need to access some data but you don't need to share it across components and don't need to change it you can use refs too.

How to Use React Context with TypeScript

React Context provides a way to pass data through the component tree without having to pass props down manually at every level. Use it when you need to share data “globally”, between many components on different levels to a component tree. To create a context use React.createContext : With TypeScript, you can declare a type for a context , so that TypeScript will know what types are acceptable for this context. However, there is a catch. If we have a data structure that can't have default values we can't just type a context: There are 2 workarounds here. The first one allows not to assign values to fields of a User type. So when we pass a defaultUser as an initial value there no errors: But in this case, we lose in type-safety a bit because we can miss some values later. The second option is to set null as an initial value: This way we don't lose in type-safety, but we will need to check if the context value is null every time we access it. When created, a context can be used in components. To give access to a context value we need to use Provider : The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider . To get a value we need to use the Consumer component: It uses a render-prop pattern . This means that it accepts a function instead of a component as a child. It will then pass a context value as an argument to this function. You can also use useContext hook to get access to a context value. This makes the component's source much simpler and cleaner.

How to Use State in React Components with TypeScript

When you need to store some data that won't be shared across components you can use the local component state. To use state in functional component use useState hook. This hook returns a tuple of two values. The first one is the current value of the state, the second one is a function to update the state. You can also increase type-safety declaring what types a state accepts: In class components, you can define a state as a class property called state . With TypeScript, you can declare a type for the state: The CounterProps type is used to declare what type the properties of this component support. The CounterState type will check the state types at the pre-compile time, so you will know earlier if there is an error. You don't have to annotate CounterState the second time inside of a component itself, but it allows better type inference when accessing this.state. Notice the React.Component<CounterProps, CounterState> type. This is the generic React.Component type. It takes two type-parameters that tell TypeScript how to interpret types of component props and state, so TypeScript can derive types of each field in props and the state. There is no need to mark types fields readonly since React.Component<P,S> already marks them as immutable. To change state in a class component use the setState method . This method enqueues changes in the state and causes a component to re-render.

The unused power of useEffect

In this post, we will discuss the useEffect hook offered to us by React Hooks which lets us perform side effects in function components.The release of React Hooks offered a new method of using React where we do not need class-based components. Before the introduction of React Hooks, all state was managed in class-based components. Function components were just used as dummy components i.e. just used to display data passed in by the use of props. Function components also offered no lifecycle methods, so knowing when the component had mounted or when it updated was very difficult and could only be handled in class-based components In addition to this, we also need some lifecycle method that would behave similarly to componentDidMount and componentDidUpdate , along came useEffect which gave us the power to handle side effects in function components. In React, there are two common side effects, side effects that require clean up and side effects that don't, useEffect can handle both of these side effects. By the end of this post, you will be able to: With the above knowledge in place, you will be able to build out an entire application with just function components. To get the most of this article, we assume you're familiar with the component basics in React & React Hooks and also core JavaScript. If you do not know any of the above but would like to learn, here are some great resources: Now let's get into it! We will first look at how we can implement useEffect into your application. The React team has made this quite simple for us. The interface for useEffect is quite simple, it accepts two arguments, a function, and an array: The first thing we need to do is import useEffect: Then we can use it in our component: Now let's look at the main points of useEffect : With all the theory we need in place, we will now look at an example in order to put our knowledge to use. It is very common to do an animation when a user sees your page, to do this we normally use a reference to the HTML element. In react, we use the useRef hook to achieve this: Then on your element: We then have reference to that element from the .current property of our sqaure ref. In our example, we want a square to be rotating when our page loads. We will be using the Greensock library for our animation as it keeps the animation code simple so we can focus on useEffect . So our component could look like this: The problem with this is that the .current property isn't available to us when the page loads. We will see the following error in the console: To remedy this issue, we can put the animation code inside of the useEffect function which won't fire until the component has loaded. Now our div will rotate when the component has loaded, if you have used React before then this is very similar to componentDidMount . The console will also have no errors. Here is a link to a Codesandbox that you can play around it: Updating the document is also another very common example of using useEffect . So if you had an array of names declared like so: We can store one of these names in state : We can add a button that onClick will pick a random name: So when this button is clicked we want to update a div that has the class of title . The code will look as follows: We want this to change every time that currentName is updated, we do this by adding the above like inside of useEffect . So every time our currentName changes, useEffect tells our component of what it needs to do when an update is performed i.e. in our case update the innerHTML . The is the pattern of useEffect , state updates --> run function . In our next example, we will look at changing this pattern. Here is the complete Codesandbox: Our final example is the most complicated but will help to even further our knowledge of useEffect . In this example, we will also be using the second argument that we can pass to useEffect . For our API, we are going to use the free PokeAPI . We can query this API with an id and it will return the Pokemon who belongs to that id , the id can be passed as a prop to the component. Finally, to fetch the data, we will be using axios . Our request will look like as follows: So above the ${id} part of our query string is the id that the user of the component will provide as a prop . When fetching data with React Hooks, you should place the code in useEffect so that the data will be fetched when the component mounts. You can do this like so: We declare some state initially where we can store our data, and then using the setter ( setData ) we can update state of our component. You will also see that I am using async and await which is handling the promise being resolved. If you were to run this code you would encounter a nasty bug, since we haven't supplied an array of dependencies (i.e. the second argument) we will get stuck in an infinite loop. Our component will mount, then update our state which will cause the useEffect function to fire again which will go through the entire process again and again and again...... How do we fix this? We supply an empty array to the second argument of useEffect . This second argument is to define all the variables that the hook depends on i.e. the variables it needs to watch for changes, in our case, it depends on none so this will stop useEffect running on component update. Great! So there is one last thing we have to deal with. The above code in Codesandbox gives the below error. It is telling us that the callback we pass to useEffect shouldn't be asynchronous and instead, we should place the asynchronous function inside of the callback. Thankfully, this is quite an easy fix. We need to create a function inside useEffect that will be our async function and then within that function we can make our request with await and set our state. Then we simply call that function within the useEffect block. Here is how it looks now: Great! That is how you fetch data with useEffect , not so bad right? Here is a Codesandbox that you can play around with: Today we learned: In addition to the above, we also learned how to use useEffect to manage that action we take when our component updates. We saw how useEffect can handle side effects in our components such as DOM manipulation and API requests. If you're interested in learning further, I really recommend checking out this long-form post by Dan Abramov . Have a great day.

Thumbnail Image of Tutorial The unused power of useEffect