React Hooks: Cheat Sheet, with examples
Tags: react, beginners, javascript, webdev
Published: 2023-08-08 16:02:08

In this article we are going to learn about react Hooks, What are the types of hooks, built-in hooks, how you can combine multiple hooks to create your own hooks

## What are Hooks?
To understand react hooks, let us first consider what are functional components?

Functional components at their core are functions, and as with all javascript functions you can use one function inside of another function.

Hooks are functions that let you use different react features in your components. You can import built-in hooks or create your own custom hooks by combining one or more built in hooks

This article is brought to you be DeadSimpleChat, [Chat API](https://deadsimplechat.com) and SDK for website and Apps. Using which you can easily add in-app messaging to your app

Let us learn about built in hooks and how you can combine them to create your own hooks with examples

## Types of built-in hooks

**State Hooks**

- `useState`

- `useReducer`

**Context Hooks**

- useContext

**Ref Hooks**

- useRef

- useimperativehandle

**Effect Hooks
**
- useEffect

- useLayoutEffect

- useInsertionEffect

**Performance Hooks**

- useMemo

- useCallback

- useTransition

- useDeferredValue

**Other Hooks**

- useDebugValue

- useId

- useSyncExternalStore

**Creating your own Hooks**

## State Hooks

React State basically lets a component remember the data, any data that you would like to store can be stored in State

State is a javascript Object, that stores the data that is specific to the component inside of which the state is defined.

To add `State` to a component, use one of the following hooks

1. `useState` declares a state variable which can be assigned to any data and updated directly

2. `useReducer` declares a state variable inside a reducer function with update logic

Now, let us look at some of the examples

#### Example 1:

#### initializing the state

```javascript
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  // rest of the component
    
}
```
Here we are initializing state using the `useState` hook. The hook is a function that takes the initial state as an argument and returns an array with current state and a function to update the current state

#### accessing the state
To access the state just refer to the variable that you have defined while initializing the state, like so

```javascript
<p>
    the count = {count}
</p>
```
#### updating the state

simply call the update function and assign the new value of state to the function

```javascript
setCount(count + 1);
```

**Note: The component re-renders whenever the state is updated**

#### Example 2:
Let us look at another example with `useReducer` . When you have many state updates across many event handlers it can get overwhelming.

In these cases you can consolidate all the state logic outside your component in a single function called the reducer

Reducer is a pure function that takes the current state and an action then returns the new state

```javascript
import React, { useReducer } from 'react';

// current state and action are recieved and new state is returned
const counterReducerFunc = (state, action) => {
  switch (action.type) {
    case 'increase':
      return { count: state.count + 1 };
    case 'decrease':
      return { count: state.count - 1 };
    default:
      throw new Error(`This action is not known: ${action.type}`);
  }
};

const Counter = () => {

  const [state, dispatch] = useReducer(counterReducer, { count: 0 });

  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increase' })}>Add</button>
      <button onClick={() => dispatch({ type: 'decrease' })}>Subtract</button>
    </div>
  );
};

export default Counter;
```

## Context Hooks
Context lets you pass the data from far away (distant ) parents to child with passing it as props

As an example, Your App's top level component can pass the current UI theme to all components below no matter how deep.

With react context you are able to avoid what is called as 'prop drilling' where you passing down the data from one component to its child, then from child component to its child component

With context all the data is provided to every component that subscribes to the context

1. `useContext` reads and subscribes to a context

#### Example
Let us understand the `useContext` with the help of an example

First, we are going to create a context by using `React.createContext()` method

```javascript
const SomeContext = React.createContext();
```

#### Providing value to react context
The `SomeContext.Provider` component is used to provide a context value to all the children in the component tree

You can then place the `SomeContext.Provider` anywhere in the tree where you need to access the value

#### Consuming the Context value with useContext

To access the value from context simply use the useContext Hook inside your component

`useContext` takes the context Object that is 'SomeContext' here and returns the current context value like so

```javascript
const ChildComponent = () => {
  const currentContextValue = useContext(SomeContext);
  
  return <p>{CurrentContextValue}</p>; // "We have electricity"
};
```
`useContext` provides the context value directly to the child components without the need to pass the data using props.

#### Ref Hooks

The Refs lets a component hold a value that is not needed for rendering.

This value can be a DOM node or a timeout ID. Unlike a state updating a ref does not re render a component.

Refs are sort of an escape hatch from the react paradigm,

Refs can be useful when working with non react systems like Rest APIS, or to store previous state values, accessing the DOM directly or keeping any mutable values.

There are two hooks that deal with refs

1. `useRef` declares a ref and you can hold any value in it
2. `useImperativeHandle` lets you customize the ref exposed by the component. This hook is rarely used

Let us look at some examples to better understand this

### Example

#### Creating a Ref

you can initialize the ref like this

```javascript
const exampleRef = React.useRef();
```
The ref object here that is exampleRef will persist throughout the lifetime of the component

#### accessing the values inside of a Ref

You can easily access the values inside of the Ref by using the .current property like

```javascript
exampleRef.current = "We got the power";
console.log(exampleRef.current); //outputs "We got the power";
```

#### Accessing DOM elements

In this example we are going to access a DOM node directly for something that can't be done in react declarative

lets see the example:

```javascript
import React, { useRef } from 'react';

const SampleComponent = () => {
  const inputRef = useRef();

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleClick}>On button click focus on the input tab</button>
    </div>
  );
};

export default SampleComponent;
```

In this example we have input element to the inputRef ref and when the handleClick function is called it focuses on the input element using the `inputRef.current.focus()` method

## Effects Hooks

Effects lets a component connect to and synchronize with external systems

This includes dealing with DOM, widgets that were written using a different UI library and other non react code.

Basically, `useEffect` lets you perform side effects in functional components. This includes interaction with outside of the component like data fetching, subscriptions, manual DOM manipulations etc.

Effects are an escapse hatch from the react ecosystem. So, do not use effects to orchestrate the data flow of your application as this might defeat the basis of using react and create multiple problems.

If you are not interacting with systems outside of React, you might not need to use Effect.

Let us look at examples to better understand the useeffect hook:

```javascript
import React, { useEffect } from 'react';

const CoolComponent = () => {
  useEffect(() => {
    console.log('Rendering the component on the display');
  });

  return <h1>using the useEffect </h1>;
};

export default CoolComponent;
```

In this example when the CoolComponent is rendered, the console.log statement written within the function will print the **'Rendering the component on the display'**

Now, let us look at two other variations of `useEffect`

`useLayoutEffect` and

`useInsertionEffect`


`useLayoutEffect` runs similarly to the `useEffect` but runs synchronously after all the DOM mutations are done. This makes it a good tool for reading the layout from the DOM and re-rendering

So, if you need to measure a DOM node and then cause a synchronous re render, you can use the `useLayoutEffect`

`useInsertionEffect` is a react hook designed for developers working on CSS in JS libraries

Using this hook you can inject styles into the DOM before layout effects are fired, ensuring that these styles are available immediately when the component renders

the `useInsertionEffect` accepts a setup function and an optional dependency array similar to other hooks

## Performance Hooks

Skipping unnecessary work is a common way to optimize re-rendering performance.

That is if the data has not changed from the previous re-render, you can tell react to skip the re-render or to skip the calculations thus saving resources

React provides several hooks to optimize the performance of your components and these are:

To skip calculations and avoid re-rendering of components you can use

1. `useMemo` :Lets you cache the result of an expensive calculation

2. `useCallback` : Lets you cache a function definition before passing it down to an optimized component

Sometimes, you can't skip the re-rendering because the screen needs to update.

In this case you can improve performance by separating the blocking updates that must be synchronous from non-blocking updates which do not need to block the UI

In these cases you can use one of the following hooks

#### useMemo

`useMemo` memorizes the result of a function. let us learn more about this using an example

```javascript
import React, { useMemo } from 'react';

const CoolComponent = ({ values }) => {
  const expensiveCalculation = useMemo(() => {
    return values.reduce((big, expensive) => big + expensive, 0);
  }, [values]);

  return <div>{expensiveCalculation}</div>;
};

export default CoolComponent;

```

In the above example `useMemo` memorizes the result of the `expensiveCalculation` and only perform the calculation if the props change

#### useCallback

`useCallback` is similar to useMemo but it returns a memorized version of the callback function that only changes if one the dependencies have changed

let us consider an example

```javascript
import React, { useState, useCallback } from 'react';

const CoolComponent = () => {
  const [count, setCount] = useState(0);

  const increaseTheCount = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return <button onClick={increaseTheCount}>Increase the Count</button>;
};

export default CoolComponent;
```
Here we are using the `useCallback` function to create a memorized version of  the `increaseTheCount` function that only changes when the count changes

#### useTransition

`useTransition` is a hook that manages transitions on slow networks and devices.

It returns two values

- a `startTransition` function and

-  an `isPending` boolean

Let us consider an example

```javascript
import React, { useState, useTransition } from 'react';

const CoolComponent = () => {
  const [resource, setResource] = useState(null);
  const [startTransition, isPending] = useTransition();

  const GettingTheResource = () => {
    startTransition(() => {
      fetchResource().then(setResource);
    });
  };

  return (
    <div>
      <button onClick={GettingTheResource}>Get the Resource</button>
      {isPending ? 'Waiting...' : <ShowTheResource resource={resource} />}
    </div>
  );
};

export default CoolComponent;
```

In the above example the `usetransition` is used to provide a smooth transition when the app is fetching a resource.

The `isPending` value can be used to show a loading screen while the resource is being fetched over the internet

### useDeferredValue
Lets you defer a non-critical part of the UI and lets the other parts display first

Let us consider an example to better understand this

```javascript
import React, { useState, useDeferredValue } from 'react';

const CoolComponent = () => {
  const [writeUp, setWriteUp] = useState('');
  const deferredValue = useDeferredValue(writeUp);

  return (
    <div>
      <input
        value={writeUp}
        onChange={e => setWriteUp(e.target.value)}
      />
      <SlowComponent setWriteUp={deferredValue} />
    </div>
  );
};

export default MyComponent;

```

In this example the `useDeferredValue` is used to defer the value of the writeUp as that is less important than showing the `input` tab to the user first


### Other Hooks
These are some of the other interesting built-in hooks available

1. `useDebugValue` You can customize the label that the React DevTools displays for your custom with with useDebugValue

2. `useId` Associate a unique ID with a component. You can use this with accessibility APIs

3. `useSyncExternalStore` subscribe a component with an external store

Let us consider some examples to understand these hooks better

### useDebugValue

```javascript
import { useState, useDebugValue } from 'react';

function useChatStatus(userId) {
  const [isOnline, setIsOnline] = useState(null);

  // show a lable next to this hook in react Dev tools
  useDebugValue(isOnline ? 'Online' : 'Offline');

  return isOnline;
}
```
In the above example we are using `useDebugValue` to show a custom hook `useChatStatus` in the react devtools

### useId

`useId` is a react hook that can be used to create multiple unique ids that can be passed to  accessibility attributes

let us consider an example to learn better

```javascript
import { useId } from 'react';

function PasswordField() {
  // useId is used to generate a unique ID
  const passwordHintId = useId();

  return (
    <>
      <label>
        Password:
        <input type="password" aria-describedby={passwordHintId} />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 18 characters
      </p>
    </>
  );
}

export default function App() {
  return (
    <>
      <h2>Choose password</h2>
      <PasswordField />
      <h2>Confirm password</h2>
      <PasswordField />
    </>
  );
}
```

In the example the `useId` is used to generate unique ids for the description paragraph of the password input. If the `PasswordField` is used multiple times across the app the generated ids will not clash

Reason behind using `useId` for generating ids instead of an incrementing counter

you could simply increment the Global counter like `count++` to generate new ids

The primary reason is that the `useId` maintains compatibility with the server rendering.


## Creating custom hooks

You can also define your own custom hooks as javascript functions. 

This involves extracting the duplicated logic that is being re used in multiple components into a separate function

The function will be called a Hook. The name of the hook always starts with the word use

There can be multiple hooks within a hook, like there can be multiple functions inside of a function

The returned values can be anything like functions, state, or any other value that you want to share between components

let us create the `useOnlineUserStatus` Hook as an example to better understand this topic

**What is the Shared Logic** In this case the shared logic is whether the user is online or not. This shared logic can be useful to multiple components

**Create a function with the starting keyword use** As we have already decided that the name of our hook will be `useOnlineUserStatus`.

```javascript
function useOnlineUserStatus() {

}
```
Moving the shared logic into the function that we just created

```javascript
import { useState, useEffect } from 'react';

function useOnlineUserStatus() {
  const [isUserOnline, setIsUserOnline] = useState(true);

  useEffect(() => {
    function handleOnline() {
      setIsUserOnline(true);
    }

    function handleOffline() {
      setIsUserOnline(false);
    }

    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return isUserOnline;
}
```
**return** Here we are returning the data the other components might need that is the status of the user.

**Using the Custom Hook in your code**

You can use the custom hook in your component like any other hook

```javascript
function ShowOnlineUserStatus() {
  const isUserOnline = useOnlineUserStatus();
  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}
```
Thus we have created a custom hook

## Conclusion

In this article I have covered a wide range of topics regarding the React Hooks, including types of hooks their use cases and how to use them in your code

I hope that you liked the article. Thank you for reading