React Hooks in a Nutshell (Incl Data Fetching, Custom Hooks, Context and Usages)
Tags: react, reacthooks, javascript, hooks
Published: 2019-10-09 17:59:32

---
title: React Hooks in a Nutshell (Incl Data Fetching, Custom Hooks, Context and Usages)
published: true
description: Learn All The Important Parts Of React Hooks like data fetching, custom hooks, context, lifecycle emulation, etc
tags: #react #reacthooks #javascript #hooks 
---

So this is my attempt to give people who are new to hooks a **quick** overview of the most important hooks that you should know alongside basic examples of usage of each one to get you started.


Now off we go .


![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/g99oo0exqnkjydz4010s.png)


# General intro

There are multiple (seemingly unrelated) problems that hooks attempt to tackle, but for the sake of keeping this as short as possible, you should know that hooks allows you to:

- Have state in your functional component
- Reuse a piece of state logic in multiple components
- Simplify your logic when it gets too big

Let's start with the first hook

# useState

useState is the hooks way to have state in your functional component, so for example say you're implementing a clap counter, you'd normally achieve this by implementing a class based components like this:

```javascript
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      claps: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.claps} times</p>
        <button onClick={() => this.setState({ claps: this.state.claps + 1 })}>
          Clap
        </button>
      </div>
    );
  }
}
```

well, in hooks you can do the same writing this:


```javascript
function Example() {
  const [claps, setClaps] = useState(0);

  return (
    <div>
      <p>You clapped {claps} times</p>
      <button onClick={() => setClaps(claps + 1)}>
        Clap
      </button>
    </div>
  );
}
```

And voila, you got a fully *functional* state (pun intended) .
That `const [claps, setClaps] = useState(0);` line utilizes array destructuring, which was introduced in *ES6*
 
`claps` is our state field, and it will have an initial value of whatever we pass to `useState`, which is in that case was `0`, so initially claps will be equal to `0`

`setClaps` is the function that we will use to modify that `claps` state field, as you can see happen when we *click* on our *clap* button, this will fire the `onClick` and the `setClaps` will be called with the existing value of `claps` plus `1`, which will be the `claps` field new value


And that covers the first hook !

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/rzvnm35yv4kv4kfkj8wb.jpg)

# useEffect

The `useEffect` hook can be used to *emulate* alot of the existing lifecycle methods like `componentDidMount`, `componentWillUnmount` and `componentDidUpdate` (and some of the older lifecycle methods ofocourse like `componentWillRecieveProps`)

But before we see usage example, you should know that `useEffect` take in 2 params, a function and an array.

The array (let's call it dependencies array) will consist of the names of the values that, when changed, will have the function - the first param - called

#### what if we didn't have a dependency array?
- that means that the useEffect function -it's first param- will run on every render, which is usually not what we want

In a later example we'll mention what happen if the dependency array is empty


### React to state/props change

So let's see an example

Say you want to do something every time the user claps, for the sake of an example, say you want to `console.log` a "You clapped" message, with the `useEffect` hook we can do that this way

```javascript
function Example() {
  const [claps, setClaps] = useState(0);
  
  useEffect(()=>{
     console.log("You clapped");
  },[claps])

  return (
    <div>
      <p>You clapped {claps} times</p>
      <button onClick={() => setClaps(claps + 1)}>
        Clap
      </button>
    </div>
  );
}
```

So what happens here is that every time a state field changes, react checks all of our useEffect (yes there can be a multiple of them in our code, just like there can be multiple state fields defined using `useState`) and it fires all the functions in the `useEffect` that, in their dependency array, have the field that got changed


So in our case, when we click on our *clap* button, the `setClaps` function is called, the `claps` state field gets changed, which leads to this useEffect first param (it's function) to be called since it's dependency array contains the `claps` field

```javascript
    ...
    useEffect(()=>{
       console.log("You clapped");
    },[claps])

    ...
```

So this was basically how to emulate `componentDidUpdate` 

This structure can of course also be used to call your useEffect hook function when a prop change, simply by adding whatever props you want to be taken into consideration to the dependency array, so if claps are gotten from the component's parent for example:

```javascript
function({claps}){
    useEffect(()=>{
       console.log("You clapped");
    },[claps])
    ...
}
```

Also, since it's called a dependency *array*, remember that you can have multiple values in it, and the function will get fired if one or more of the values in the dependency array get changed

### Data fetching

useEffect can also be used to fetch data, but the key question to ask before using this hook to fetch data is :

#### what if the dependency array was empty?
- that means the hooks won't run on every render since we explicitly told it to not watch over any variables, so it will only run on mounting

Which is usually what we want when we want to fetch data

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1ukufteolha0d7c84d85.jpeg)


So now that we know how to make the useEffect only run on mounting (emulating the componentDidMount lifecycle), fetching data is as simply as doing this:


```javascript
    function App(){
      const [data,setData] = useState([]);

      useEffect(()=>{
       const data = await axios('https://datafetchingexample/data');
       setData(data);
      },[])

      ...
    }
    
```

### Cleaning up 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/e0j6je7mgv1rdohyuf6j.jpg)

Next up is figuring out how to use `useEffect` to do any clean up that we want to do in our component


```javascript
    function App(){
      const [data,setData] = useState([]);

      useEffect(()=>{
        const source = axios.CancelToken.source();

        const data = await axios('https://datafetchingexample/data');
        setData(data);

        return () => {
          source.cancel();
        };

      },[])
      
    
      ...
    }
    
```

So as you might've noticed, we added a return in our hook, this return function will run when the component unmounts, making it the perfect place to do any cleaning up (closing a socket, unsubscribing, cancelling a request, etc...basically same usage as componentWillUnMount)


# useContext
 
Next up, using context with hooks 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/h8bku4afcb0ygdwyeisw.jpg)

Context is, as you may know, react's way to manage state across components, basically it's react's own redux in a way

It's used when you have some data in a component that you want descendants of that components (direct children or indirect descendants in general) to have access to, so for example say we have a component that fetches data and you want to pass that data to your child, obvious way to do that is using props, but if you want to have that data in your grand grand grand grand child...that's where using props can turn into more of a hassle and where using context makes more sense.

For the sake of explanation however, let's say you want to pass this data to your direct child


So first, we'll create  a context that has a value of an empty object 
`const DataContext = React.createContext({});`
Next you should wrap the component you want to pass the context to in 
`<DataContext value=somevalue></DataContext>` 
Which is what we did to our child component, all we have to do this is just determine the value of the context through the value property 
(in that case we want to pass the data field), so we did


```javascript
    ...

    const DataContext = React.createContext({});

    function App(){
      const [data,setData] = useState([]);

      useEffect(()=>{
        const source = axios.CancelToken.source();

        const data = await axios('https://datafetchingexample/data');
        setData(data);

        return () => {
          source.cancel();
        };

      },[])
      
    
      return (
         
         <DataContext value={{data}}>
           <Child/>
         </DataContext>
  
      )
    }
    
```
Now moving on to our child component, all we have to do is use the `useContext` hook, pass the context object that we want to it, and simply get data that we added in the `value` attribute


```javascript
    ...


    function Child(){
      const {data} = useContext(DataContext);
      
    
      return (
         
         <ul>
           data.map(v=>{
             return (
               <li>
                 {v.value}
               </li>
             )
           })
         </ul>
  
      )
    }
    
```


So now that we've covered arguably the 3 most popular hooks, let's talk about the general rules of hooks

# Hooks Rules

#### Only call hooks at the top level

This means that you should *not* use hooks inside loops,if conditions or nested functions, you should always use hooks at the top level of your react function, that's because hooks depend on the order that they are initialized in, so if you for example add a hooks inside a hook in an if condition, that if condition might not be happening in the next render, leading to a disorder in the hooks, we'll talk more about this in another article

#### Don't call hooks in javascript functions

You can call hooks from 2 places

- react functional components
- custom hooks, which we will talk about next


# Custom hooks

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/pq5c329s3zsqhih5scx0.jpg)

Now for the last and the core piece of react hooks, making your own custom hooks.

Custom hooks are javascript functions whose name start with `use` and it has the ability to call other hooks (custom or built in)

Building a custom hook means that you get to extract a piece of logic for you to use it in multiple places, for example, say you got a couple of inputs that accepts name and age



```javascript

function InputForm(){
  const [name,setName] = useState("")
  const [age,setAge] = useState(0)

  return (
    <div>
       <input type="text" placeholder="Enter your name" value={name} onChange={(e)=>setName(e.target.value)/>
       <input type="number" placeholder="Enter your age" value={age} onChange={(e)=>setAge(e.target.value)}/>

    </div>
    
  )

}
```

Now, basically all inputs in our app will have a similar structure, input field with value,onChange attributes, and not only in this file, using state to handle input can in multiple files that you have, custom hooks will let us extract that piece of reusable logic to use it elsewhere 

it will look something like this :



```javascript

function useFormInput(initialValue){
  const [value,setValue] = useState(initialValue);
  function onChange(e){
    setValue(e.target.value);
  }
  return {value,onChange};

}

function InputForm(){
  const name = useFormInput("")
  const age = useFormInput(0)

  return (
    <div>
       <input type="text" placeholder="Enter your name" {...name} />
       <input type="number" placeholder="Enter your age" {...age} />
    </div>
    
  )

}
```

Cleaner isn't it? this will have the same affect as the regular way of doing things but now you have a reusable hook that let you have inputs with their changing functionality anywhere in the app, just use the hooks, destructure the value returned in your input tags, and you're good to go !

If you think you need to practice more on the subject while building 4 projects, I encourage you to take a look at this course : 

https://www.udemy.com/course/react-hooks-projects-course/