# React Hooks

## Summary


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?

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?

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?

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?

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?

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.