React Hooks

React is based on components. The logic to manage component state and update the user interface is encapsulated with the component. But what if we wish to reuse stateful logic across components, such as for logging or authentication? React allows this via mixins, higher-order components and render props. However, these complicate the component hierarchy. React Hooks provide a cleaner and more elegant way of doing this.

React's function components are stateless and without side effects. React Hooks combines the simpler syntax of function components but allows for states and side effects.

Class components continue to be available in React. Hooks can coexist with class components, although they can't be used inside a class. In fact, React concepts such as props, state, context, refs and lifecycle are still relevant in Hooks.

Discussion

  • What are the advantages of using React Hooks?
    Hooks help organize code into separate logical units (eg. theme, names, width). Source: Pai 2018.
    Hooks help organize code into separate logical units (eg. theme, names, width). Source: Pai 2018.

    React Hooks solves the problems of class components. With Hooks, we can reuse stateful logic without complicating component hierarchy.

    Class components may have code repetition. For example, code may be repeated in lifecycle events componentDidMount and componentDidUpdate. Custom Hooks enable easy code reuse.

    Developers coming from other languages have a hard time understanding the this reference. Class components tend to be verbose. They don't minify well. Hot reloading is unreliable. Hooks offer developers a way to more effectively use React's features.

    Code is harder to organize logically in class components. For example, fetching data and setting up event listeners are doing different things but they're probably mixed together in the same lifecycle method. Fetching data and its clean up is also likely to be split between componentDidMount and componentWillUnmount. With Hooks, we can organize logical units of code into functions. For this reason, Dan Abramov noted,

    Hooks apply the React philosophy (explicit data flow and composition) inside a component, rather than just between the components.
  • Could you explain React Hooks with an example?
    A simple React Hooks example. Source: Adapted from React Docs 2019b.
    A simple React Hooks example. Source: Adapted from React Docs 2019b.

    The figure shows an example that uses two types of Hooks: useState and useEffect. We note that Hooks are used within a function component, not a class component. Instead of the render() method found in class components, we simply return the component at the end, whose syntax is in JSX format. We no longer use the this variable that was common in class components.

    This component maintains a state called count that can be set with a function named setCount(). Both these are returned by useState. setCount() is triggered when the button is clicked. This updates the state, which in turn triggers a re-rendering of the component.

    After the component is rendered or re-rendered, the useEffect Hook is triggered. This simply updates the document title in this example.

    Finally, we observe that Hooks are called in response to UI events, DOM rendering, etc. Therefore, they're not independent of React lifecycle methods. React Hooks "hook into" React state and lifecycle features from function components.

  • Which are the Hooks that React provides?

    Among the basic Hooks are useState, useEffect, and useContext. Additional Hooks include useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, and useDebugValue. We briefly describe these (refer to the Hooks API for more details):

    • useState: Initializes and manages component state.
    • useEffect: Called after DOM is rendered to the screen. Side effects such as logging or timers can be executed here.
    • useContext: Accepts a context object and returns its current context value based on the nearest ancestor's value prop.
    • useReducer: Better than useState for managing complex state logic.
    • useCallback: Given a callback and its dependencies, obtain a memoized callback. Useful to prevent unnecessary rerenders.
    • useMemo: Optimize expensive computations by returning a memoized value. Recomputes happen only when dependencies change.
    • useRef: Create a container to hold a mutable value. Useful for accessing child elements imperatively.
    • useImperativeHandle: Customize instance value that's exposed to parent components. However, prefer to avoid imperative code.
    • useLayoutEffect: Like useEffect but called synchronously before browser "paints" the screen. Useful to avoid flicker when an effect manipulates DOM.
    • useDebugValue: Display a label for custom Hooks in React DevTools. Useful when such Hooks are part of shared libraries.
  • What's the React Hooks lifecycle?
    React Hooks lifecycle. Source: West 2019.
    React Hooks lifecycle. Source: West 2019.

    Function components with Hooks can be mounted, updated and unmounted. Each of these go through the render phase and commit phase. During the latter the DOM is updated.

    Different Hooks are called at different phases of the React Hooks lifecycle. useMemo is called during the render phase when the component is mounted. useState, useReducer, useContext and useCallback are called during the render phase when component state is updated. Render phase is not the place for executing side effects.

    useLayoutEffect and useEffect are called after React has updated the DOM but there's an important difference. useLayoutEffect is called synchronously. It will block the browser before browser has had a chance to "paint" the screen. useEffect is called after browser has painted the screen. Generally, useEffect is preferred unless the Hook makes visual updates to the DOM.

    Both useLayoutEffect and useEffect are also called when the component is unmounted, provided these Hooks return a callback function.

  • Could you describe the State Hook?

    The most basic Hook is useState. This takes an initial value and returns a stateful value plus a function to update it. When the component first renders, returned value is same as initial value. Next time the component renders, the current state is available, that is, it's not initialized again. This is what React Hooks enables. For expensive computation, a function can be passed into useState.

    For updating state, a value can be passed to the update function, fn(val). If current value is needed for the update, a function can be passed, fn((c) => c+1). Where state contains sub-values such as {name: 'john', age: 22}, useState doesn't merge the values. We need to use the spread syntax, {...prevState, ...updatedValues}.

  • Could you describe the Effect Hook?

    Hook useEffect allows us to perform side effects, such as fetching data or updating DOM. Having these side effects inside the main body of the function component (used during the render phase) can result in UI bugs and inconsistencies. Hence, use this Hook to implement side effects.

    This Hook enables imperative programming, as a feature that complements React's purely functional programming approach. It accepts a function as an argument and optionally a second argument. Without the second argument, the Hook is called after every render. If the second argument is an empty array, the Hook is called only once. If array is non-empty, the Hook is called conditionally only when those dependencies change.

    The Hook can also return a function, which is called when the component unmounts.

    Having this Hook inside the component allows it to access component state. This state is never stale since with each render we recreate the function wired to the Hook.

  • What are the rules of Hooks?
    ESLint configuration for React Hooks. Source: React Docs 2021b.
    ESLint configuration for React Hooks. Source: React Docs 2021b.

    React Hooks have only two essential rules that developers need to follow. Hooks should be called only at the top level within the component. Don't call them within loops, conditions or nested functions. This is because React Hooks expects that Hooks are always called in the same order whenever the component renders.

    The second rule is that don't call Hooks from regular JavaScript functions. Call them only from React function components or from custom Hooks. This ensures that all stateful logic is visible within the component's source code.

    To ensure that components meet these rules, developers can install the React Hooks ESLint Plugin, aka eslint-plugin-react-hooks on NPM. The plugin will warn developers when these rules are violated. When we create the default React app, this plugin is installed by default.

  • Can class components interoperate with React Hooks?
    Some React lifecycle methods and their equivalents in React Hooks. Source: Adapted from React Docs 2021d and Makadia 2020.
    Some React lifecycle methods and their equivalents in React Hooks. Source: Adapted from React Docs 2021d and Makadia 2020.

    React Hooks don't replace class components. An application can use class components, function components and Hooks. In fact, these approaches can be used in the same DOM tree. However, at code level, it's not possible to use React Hooks within a class.

    Developers can adopt Hooks for new components. Legacy components could be migrated to Hooks incrementally. Particularly for render props and higher-order components, Hooks offer a simpler approach and reduce nesting of DOM elements.

    To relate to component lifecycle methods, we note the following:

    • constructor: Not required in Hooks. Initialization can be done with useState.
    • getDerivedStateFromProps: Update component while it's being rendered.
    • shouldComponentUpdate: Wrap a function component within React.memo, a higher-order component. This is not exactly a Hook. Compares props (not states) in a shallow manner.
    • render: Function component body is returned.
    • componentDidMount, componentDidUpdate, componentWillUnmount: useEffect Hook can implement all three.
    • getSnapshotBeforeUpdate, componentDidCatch, getDerivedStateFromError: No equivalent in Hooks.
  • What are some criticisms of React Hooks?

    For someone used to class components, React Hooks is something new to learn. Learning fatigue is common among JavaScript developers. The new knowledge is React-specific and can't be reused anywhere else.

    React Hooks can't be used with class components. This means that legacy code needs to be migrated, which presents the risk of introducing bugs. Developers can't also opt-out, despite what the documentation claims. There's a good chance that the ecosystem and dependencies will move to React Hooks. When that happens, our own projects will have no choice but to adopt it.

    Some may find that the rules of React Hooks are rather limiting. Reading and understanding component code and its control flow can be hard when a component uses many types of Hooks. Control flow is determined by component lifecycle and not the ordering in the source code.

    Where dependencies are passed to a Hook, object comparison works as intended for primitive types but not for arrays or other objects. Comparison is by reference and developers can't customize this.

  • Where can I learn more about React Hooks?

    The section on React Hooks in the React official documentation is a good place to start. The same documentation also has the Hooks API Reference. There's a section on building custom Hooks.

    Those who like to learn from examples, can visit the useHooks website. Some examples include show/hide UI elements, subscribe to Firestore data, handle asynchronous calls, render component based on current state of user authentication, sync state to local storage, and more.

    Xebia has published a useful React Hooks cheat sheet. This includes class-style and Hooks-style code for comparison. Emmanuel's cheat sheet is also worth reading.

    Gunawardhana has shared a list of ten useful React Hooks libraries. Mostly, these are custom Hooks built on top of the built-in React Hooks.

    Aryan's shares one approach to testing React Hooks.

Milestones

May
2013

Facebook open sources React at the JSConf US. An earlier prototype of this can be traced to 2011 and then developed within Facebook during 2012.

Feb
2019

React v16.8.0 is released. This introduces React Hooks. In the change log, it's described as "a way to use state and other React features without writing a class." This change affects React DOM, React DOM Server, React Test Renderer and React Shallow Renderer. All of these must be at least version 16.8 to use React Hooks. This release also includes the React Hooks ESLint Plugin for linting.

Mar
2019

React Hooks becomes available in React Native v0.59.

Aug
2019

React v16.9.0 is released. The React Hooks ESLint Plugin is updated to treat the use of Hooks at module level (outside a function component) as a violation.

Oct
2020

React v17.0.0 is released. As an experimental Hook, unstable_useOpaqueIdentifier is added.

References

  1. Abramov, Dan. 2018. "Making Sense of React Hooks." On Medium, October 30. Accessed 2022-01-16.
  2. Abramov, Dan. 2019. "[ESLint] Forbid top-level use*() calls." Issue #16455, React on GitHub, Facebook, August 20. Accessed 2022-01-17.
  3. ACM Hack. 2019. "A Gentle Introduction to React Hooks." ACM Hack, UCLA, October 22. Accessed 2022-01-16.
  4. Aryan, Avi. 2020. "A Complete Guide to Testing React Hooks." Toptal, July 23. Accessed 2022-01-16.
  5. Cowan, Paul. 2021. "Frustrations with React Hooks." Blog, LogRocket, April 26. Accessed 2022-01-16.
  6. Dodds, Kent C. 2020. "useEffect vs useLayoutEffect." Blog, December 1. Accessed 2022-01-16.
  7. Gunawardhana, Piumi Liyana. 2021. "Top 10 React Hook Libraries." Blog, Bits and Pieces, on Medium, May 11. Accessed 2022-01-16.
  8. Makadia, Harsh. 2020. "Replacing Lifecycle methods with React Hooks." JavaScript in Plain English, on Medium, April 26. Accessed 2022-01-16.
  9. Pai, Sunil. 2018. "ok so - I took dan's classes/hooks code from react conf, blacked out..." Tweet, on Twitter, October 28. Accessed 2022-01-16.
  10. React. 2021. "CHANGELOG.md." facebook/react, on GitHub, June 29. Accessed 2022-01-16.
  11. React. 2022. "Homepage." React. Accessed 2022-01-16.
  12. React Docs. 2019a. "Using the State Hook." Documentation, React, May 3. Accessed 2022-01-16.
  13. React Docs. 2019b. "Using the Effect Hook." Documentation, React, August 12. Accessed 2022-01-16.
  14. React Docs. 2020a. "Hooks at a Glance." Documentation, React, July 27. Accessed 2022-01-16.
  15. React Docs. 2020b. "Building Your Own Hooks." Documentation, React, March 9. Accessed 2022-01-16.
  16. React Docs. 2021a. "Introducing Hooks." Documentation, React, July 26. Accessed 2022-01-16.
  17. React Docs. 2021b. "Rules of Hooks." Documentation, React, February 27. Accessed 2022-01-16.
  18. React Docs. 2021c. "Hooks API Reference." Documentation, React, October 11. Accessed 2022-01-16.
  19. React Docs. 2021d. "Hooks FAQ." Documentation, React, April 22. Accessed 2022-01-16.
  20. React Docs. 2021e. "React Top-Level API." API Reference, React, August 9. Accessed 2022-01-16.
  21. RisingStack Engineering. 2018. "The History of React.js on a Timeline." Blog, RisingStack Engineering, April 4. Updated 2021-10-11. Accessed 2022-01-16.
  22. Shook, Dillon. 2020. "A Critique of React Hooks." Blog, April 27. Accessed 2022-01-16.
  23. Turner, Ryan. 2019. "Releasing React Native 0.59." Blog, React Native, March 12. Accessed 2022-01-16.
  24. useHooks. 2022. "Homepage." useHooks. Accessed 2022-01-16.
  25. Weber, Sebastian. 2020. "The last guide to the useEffect Hook you’ll ever need." Blog, LogRocket, November 4. Accessed 2022-01-16.
  26. West, Donavan. 2019. "Hook Flow Diagram." Tweet, on Twitter, March 10. Accessed 2022-01-16.
  27. Xebia. 2019. "React Hooks Cheat Sheet." Xebia. Accessed 2022-01-16.
  28. Yardley, Rudi. 2018. "React hooks: not magic, just arrays." On Medium, November 1. Accessed 2022-01-16.

Further Reading

  1. React Docs. 2021a. "Introducing Hooks." Documentation, React, July 26. Accessed 2022-01-16.
  2. React Docs. 2021c. "Hooks API Reference." Documentation, React, October 11. Accessed 2022-01-16.
  3. ACM Hack. 2019. "A Gentle Introduction to React Hooks." ACM Hack, UCLA, October 22. Accessed 2022-01-16.
  4. Abramov, Dan. 2018. "Making Sense of React Hooks." On Medium, October 30. Accessed 2022-01-16.
  5. Abramov, Dan. 2019. "How Are Function Components Different from Classes?" Blog, Overreacted, March 3. Accessed 2022-01-16.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
2
0
1290
1
0
8
1926
Words
0
Likes
1505
Hits

Cite As

Devopedia. 2022. "React Hooks." Version 3, February 15. Accessed 2022-04-25. https://devopedia.org/react-hooks
Contributed by
2 authors


Last updated on
2022-02-15 11:57:41