The Definitive React Hooks Cheatsheet
Tags: webdev, react, javascript
Published: 2019-04-08 22:57:03

---
title: The Definitive React Hooks Cheatsheet
published: true
cover_image: https://antjanus.com/wp-content/uploads/2019/04/react-hooks.png
canonical_url: https://antjanus.com/blog/web-development-tutorials/front-end-development/the-definitive-react-hooks-cheatsheet/
description: 
tags: webdev, react, javascript
---

React Hooks is the new hotness in the React world. I'm writing steadily more and more of them and I thought it would be useful to have a cheatsheet to refer back to which encompasses the basic hooks as well as the intricacies of `useEffect`. Check out the official [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html) for more in-depth information.

**Table of Contents**

- [useEffect for lifecycle methods](#useeffect-for-lifecycle-methods)
  - [componentDidUpdate + componentDidMount](#substitute-for-componentdidupdate-componentdidmount)
  - [componentDidMount + componentWillUnmount](#substitute-for-componentdidmount-componentwillunmount)
- [useEffect for general side effects](#useeffect-for-side-effects)
- [useState](#usestate)
- [useReducer](#usereducer)
- [Building Your Own Hooks](#building-your-own-hooks)

## useEffect (for lifecycle methods)

`useEffect`, among other things, allows you to write your own side effects and trigger a re-render when needed. 

But to make it simpler, useEffect also substitutes lifecycle methods. Let's talk about them.

### substitute for componentDidUpdate + componentDidMount

**When does it run?** On every render

**What's the catch?** It's not just a `componentDidUpdate` replacement, it also runs on mount. So it's not 1-to-1

**Important features?** useEffect can take in a 2nd argument, you *have* to skip that argument. You can also return a function, we'll cover that in the next section.

**Code sandbox playground:** [Go play with it](https://codesandbox.io/s/1r8nrzpl9j)

**Syntax:**

```js
import { useEffect } from 'react';

useEffect(() => {
  // whatever runs here will run on each re-render
});
```

### substitute for componentDidMount + componentWillUnmount

**When does it run?** On component mount and unmount

**What's the catch?** The syntax is very close to the previous use case. It threw me off several times but it makes sense once you read the docs. If the effect runs more than once, make sure you passed in the 2nd argument

**Important features?** This is an effect that runs only *once*. The mount logic goes in the body of the effect function, the unmount/cleanup logic goes into a function that you return from the effect.

**Code sandbox playground:** [Go play with it](https://codesandbox.io/s/xjrk36x244)

**Syntax:**

```js
import { useEffect } from 'react';

useEffect(() => {
  // run mount logic here such as fetching some data

  return () => {
    // unmount logic goes here
  };
}, []); // note the empty array
```

You can leave either the `mount` or `unmount` logic empty to work only off one of those lifecycle substitute. Meaning that:

1. leave `mount` logic empty so that only `unmount` logic runs (substitute for just `componentWillUnmount`)
2. return nothing so that only `mount` logic runs (substitute for just `componentDidMount`)

## useEffect for side effects

`useEffect`'s primary goal is to encompass any side effect you might want to use. A side effect is essentially *something* that you do within your component which affects the world at large. Whether that's a network request, setting the document title, or what have you.

### Run when necessary

**When does it run?** when the component re-renders, `useEffect` will check dependencies. If the dependency values changed, useEffect will run the effect

**What's the catch?** React does a shallow comparison. If you use an object or an array that you mutate, React will think nothing changed. 

**Important features** useEffect skips running the effect when things don't change. You don't actually have to use the dependency values in the effect. You can pass in a prop value as a dependency.

**Code sandbox playground:** [Go play with it](https://codesandbox.io/s/j14zoq7095)

**Syntax:** 

```js
import { useEffect } from 'react';

function SomeComponent(props) { 
    useEffect(() => {
      // logic runs only when dependency variables changed
    }, [arrOfDependency, values, props.id]); // array of values to check if they've changed
}
```

**Potential use cases** 

Since the hook is more difficult to explain, I'd like to offer a list of use cases

1. run a side effect (like a fetch) when a prop changes to get new data
2. run a resource-heavy calculation only when the calculation values change
3. update the page (like document title) when a value updates

## useState

State is probably *the* reason why people switch from stateless (functional) components to class components. `useState` allows us to have stateful components without classes.

**What does it return?** Current state and a function that lets you set state

**What's the catch?** The state setting function will replace the previous state with the new one rather than merging them as class state would have. You need to merge your objects yourself before setting the state.

**Important features** You can use as many `useState` hooks in your component as you want. Passing any value to `useState` will create the initial state. It's also a convention to not call the variables `state` and `setState` but rather by contextual names (eg. `user` and `setUser`). `useState` accepts any value for state, it doesn't have to be an object.

**Code Sandbox playground:** [Check out the useState examples](https://codesandbox.io/s/53ovy28krn)

**Syntax:** 

```js
import { useState } from 'react';

// setup
const defaultValue = { name: "Antonin" };
const [state, setState] = useState(defaultValue);

// scenario 1 usage
// resulting state only contains key `user` with value 'antjanus'
setState({ user: 'antjanus' }); 

// scenario 2 usage
// resulting state contains key `name` with value 'A. Januska'
setState({ name: 'A. Januska' }); 

// scenario 3 usage
// resulting state is a merger between `{ name: 'A. Januska' }` and `{ user: 'antjanus'}`
setState({ ...state, user: 'antjanus'}); 
```

## useReducer

`useReducer` is an alternative to `useState` and if you've used Redux in the past, this will look familiar.

**What are the arguments? What does it return?** `useReducer` takes in a `reducer` function and the `initialState`. It returns the current `state` and a `dispatcher` (sound familiar?)

**How does it run?** On state change, `dispatch` an object with a type and a data payload (read about [flux standard action](https://github.com/redux-utilities/flux-standard-action) for more info). The `reducer` we passed into useReducer will receive the current state and the dispatched object. It returns the new state.

**What's the catch?** It's a more complicated workflow but it works just like you'd expect if you've used Redux. 

**Important features** The reducer gets run on every dispatch. It gets access to the previous state. `useReducer` also includes a 3rd argument you can use to create the initial state

**Code Sandbox playground:** [Check out the useReducer example](https://codesandbox.io/s/zqj3j03jpl)

**Syntax**

```js
import { useReducer } from 'react';

function reducer(currentState, action) {
  switch(action.type) {
     // handle each action type and how it affects the current state here
  }
}

function SomeComponent() {
  const [state, dispatch] = useReducer(reducer, initialState);

  dispatch({ type: 'ADD', payload: data }); // { type: 'ADD', payload: data } gets passed into the `reducer` as the `action` argument while `state` gets passed in as the `currentState` argument
}
```

## Building Your Own Hooks

A quick note on building your own hooks. It's as easy as using the existing hooks and composing them together inside of a function that starts with `use`. Here's a quick example of a `useUser` hook.

**What are the requirements?** That the function starts with the keyword `use`. Eg. `useUser` or `useSomethingElse`.

**Important features:** you can call any hooks within your custom hook and it works as expected.


**Code Sandbox playground:** [Check out the custom hooks example](https://codesandbox.io/s/2wzponv3oy)

**Syntax:** 

```js
import { useEffect } from 'react';

function useUser(userId) {
  let [user, setUser] = useState(null);

  useEffect(() => {
    fetch(`/api/user/${userId}`)
        .then(data => data.toJSON())
        .then(data => setUser(data));
  }, [userId]);

  return user;
}

function SomeComponent(props) {
  const user = useUser(props.id);
}
```



## What about the rest?

There are other hooks you can use such as `useMemo`, `useCallback` and so on. I would say that those are more advanced hooks and if you understand the basic hooks, go ahead and check out [the official docs](https://reactjs.org/docs/hooks-reference.html).

I also understand there are some advanced usage examples for many of these (like passing useReducer's `dispatch` down several levels).

If you find something incorrect or some extra information useful that isn't included, let me know! And I'll include it!

> Did you find the cheatsheet useful? [Buy me a coffee](https://www.buymeacoffee.com/CKdpP4G) so I can keep doing this and produce more content! :) You can also [follow me on Twitter](https://twitter.com/AntJanus)