React Hooks Re-intro 
Tags: react, reacthooks, demo, tutorial
Published: 2019-04-07 21:35:21

---
title: React Hooks Re-intro 
published: true
description: React Hooks introduction, React Hooks demo, React Hooks tutorial
tags: reactjs,react-hooks,demo,tutorial
---

# React Hooks Re-intro

The original post is in this repo 
https://github.com/hayk94/react-hooks-intro-coffeeshop  
where each branch has a readme.md explaining over the code.

This repository is for React Hooks introduction.

It consists of several numbered branches.  
In each branch readme file goes over the code,  
explaining the advantages and caveats.

Here in the master branch is a plain [CRA](https://facebook.github.io/create-react-app/) app.  
There are some additional configs for eslint using [eslint-config-fbjs](https://www.npmjs.com/package/eslint-config-fbjs)  
with [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks).
And prettier config.

**Disclaimer**  

Most stuff in this repo and posts have already been discussed,  
by react team in the docs, by Dan Abramov in his amazing talk and blog,  
and other people.

This repo is just a summation of my knowledge about hooks I gathered so far.
Just putting stuff in my own words.

###### Resources

[https://reactjs.org/docs/hooks-intro.html]()

https://dev.to/dan_abramov/making-sense-of-react-hooks-2eib

https://overreacted.io/react-as-a-ui-runtime/

https://overreacted.io/making-setinterval-declarative-with-react-hooks/

https://overreacted.io/how-are-function-components-different-from-classes/

https://overreacted.io/a-complete-guide-to-useeffect/

https://overreacted.io/writing-resilient-components/


## App Intro
Imagine we are writing a coffeeshop menu app.  
Users can choose the product they want and order it.

#### Good Old Classes

First we make a` Menu.js` component.

```
import React, {Component} from 'react';

class Menu extends Component {
  render() {
    return (
      <div>
        Menu
      </div>
    );
  }
}

export default Menu;

```

And make it render in our `App.js` component.


```
import React, { Component } from 'react';
import './App.css';
import Menu from './Menu';

class App extends Component {
  render() {
    return (
      <div className="App">
        <section>
          <Menu/>
        </section>
      </div>
    );
  }
}

export default App;

```

Then we add a `select` to our menu app, with some products.  
Add a button for ordering.

```
import React, {Component} from 'react';

class Menu extends Component {
  render() {
      return (
        <div>
          <b>Order: </b>
          <select>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
          <div>
            <button>Order</button>
          </div>
        </div>
      );
    }
}

export default Menu;

```

Apparently this is what they sell at coffeeshops, isn't it?

Now we need some state for the selected product.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
      super(props);
      this.state = {
        selected: 'Purple Haze',
      };
  }
    
  render() {
      return (
        <div>
          <b>Order: </b>
          <select>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
          <div>
            <button>Order</button>
          </div>
        </div>
      );
    }
}

export default Menu;

```

Finally we need methods to select the product and order it.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
    };
  }

  onChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.selected}`);
  }
  render() {
    return (
      <div>
        <b>Order: </b>
        <select onChange={this.onChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

And here we made our app that's it.  
Now lets go and order some stuff.  

And...

Oops...

Right...

We get a big nice error message, guess what?

Turn to the next branch...

## And now this!

So now we have an error! Or rather the error...

You know it right?

Let's fix it!

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
    };
    this.onChange = this.onChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
  }

  onChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.selected}`);
  }
  render() {
    return (
      <div>
        <b>Order: </b>
        <select onChange={this.onChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

We needed to `bind` `this`.

### New Requirements

Suddenly we got new requirements from the client...  
They want the page title to be the selected item of the user.

So we need something like this.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
    };
    this.onChange = this.onChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
  }
  
  componentDidUpdate() {
    document.title = `Selected - ${this.state.selected}`;
  }
  
  onChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.selected}`);
  }
  render() {
    return (
      <div>
        <b>Order: </b>
        <select onChange={this.onChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

Lifecycle methods yay!  
Now we got it once user selects an item the document title changes accordingly.

### Yet another requirement

And now we've been given another task based on the new requirements.
Users should be able to tell us how many products they want to order.

Pretty easy, right?

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
      count: 0,
    };

    this.onProductChange = this.onProductChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
    this.onCountChange = this.onCountChange.bind(this);
  }

  componentDidUpdate() {
    document.title = `Selected - ${this.state.selected}`;
  }

  onProductChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.count} ${this.state.selected}`);
  }

  onCountChange(e) {
    this.setState({count: e.target.value});
  }

  render() {
    return (
      <div>
        <div>
          <b>Product: </b>
          <select onChange={this.onProductChange}>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
        </div>
        <div>
          <b>Count: </b>
          <input
            type="number"
            min={0}
            value={this.state.count}
            onChange={this.onCountChange}
          />
        </div>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

We add a number `input`, `count` to our state, and an `onCountChange` method.  
Oh and right, we need to `bind` `this`.

Great we accomplished a lot today and feel proud.

### Oh no, a bug was just reported

Whoops... We just barely finished the previous task,  
yet a bug was reported from our previous feature.

They say when the users enter the page first time,
the page title doesn't show the selected product.

But it's not a bug! The user didn't select any product yet!  
Oh really? It's a bug and you should fix it!

Anyway it needs to be done.  
So after thinking a while, the best place for this would be `componentDidMount`.  
Yay another lifecycle method to the rescue!

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
      count: 0,
    };

    this.onProductChange = this.onProductChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
    this.onCountChange = this.onCountChange.bind(this);
  }

  componentDidMount() {
    document.title = `Selected - ${this.state.selected}`;
  }

  componentDidUpdate() {
    document.title = `Selected - ${this.state.selected}`;
  }

  onProductChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.count} ${this.state.selected}`);
  }

  onCountChange(e) {
    this.setState({count: e.target.value});
  }

  render() {
    return (
      <div>
        <div>
          <b>Product: </b>
          <select onChange={this.onProductChange}>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
        </div>
        <div>
          <b>Count: </b>
          <input
            type="number"
            min={0}
            value={this.state.count}
            onChange={this.onCountChange}
          />
        </div>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

Phew... it's been a tough day, but we managed! Hooray!

Turn to the next branch...

### App grows! Performance issues come up!

As our app grows, we are encountering some performance issues here and there.

To identify them we start using some debugging tools.  
So you decide to put some loggers in your `Menu.js`.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
      count: 0,
    };

    this.onProductChange = this.onProductChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
    this.onCountChange = this.onCountChange.bind(this);
  }

  componentDidMount() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  componentDidUpdate() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  onProductChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    alert(`You ordered ${this.state.count} ${this.state.selected}`);
  }

  onCountChange(e) {
    this.setState({count: e.target.value});
  }

  render() {
    return (
      <div>
        <div>
          <b>Product: </b>
          <select onChange={this.onProductChange}>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
        </div>
        <div>
          <b>Count: </b>
          <input
            type="number"
            min={0}
            value={this.state.count}
            onChange={this.onCountChange}
          />
        </div>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

So we put loggers in `componentDidUpdate` and `componentDidMount`.  
Now you see the proper log after `componentDidMount`.  
You select a product and see the proper log in `componentDidUpdate`, with new state and props.  
You change the product count and see new state and props logged by `componentDidUpdate`.  

But wait a minute...  
Doesn't that mean the `document.title = newTitle` code executes on every update,  
even though the selected product didn't change?

We need to fix that. And this logger tool is really helpful we should implement it for other components too in our app.

So maybe we fix the issue with an `if` check. And make a `HOC` for the logger.

As you are thinking about the solution a new high priority requirement arrives.

Turn to the next branch...


### New Requirement with lots async stuff
So suddenly a new requirement arrives.  
To implement it you added lots of async stuff to your on order function, so now it looks like this.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
      count: 0,
    };

    this.onProductChange = this.onProductChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
    this.onCountChange = this.onCountChange.bind(this);
  }

  componentDidMount() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  componentDidUpdate() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  onProductChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    setTimeout(() => {
      alert(`You ordered ${this.state.count} ${this.state.selected}`);
    }, 3000);
  }

  onCountChange(e) {
    this.setState({count: e.target.value});
  }

  render() {
    return (
      <div>
        <div>
          <b>Product: </b>
          <select onChange={this.onProductChange}>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
        </div>
        <div>
          <b>Count: </b>
          <input
            type="number"
            min={0}
            value={this.state.count}
            onChange={this.onCountChange}
          />
        </div>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```

Everything seems to be working just fine, but then you get a bug report.  
Wrong item is being ordered sometimes.  

After trying to reproduce it for a while, you find the problem!

When you order a product then select another product before the order message appeared,  
you get a wrong product in the message as it appears.

Hmmm...
Why that would happen? Nothing seems to be wrong with our code.

Turn to the next branch...


### Ugh not this again!

So why that bug happens?

To give you a hint, lets take a look at the solution first.

```
import React, {Component} from 'react';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 'Purple Haze',
      count: 0,
    };

    this.onProductChange = this.onProductChange.bind(this);
    this.onOrder = this.onOrder.bind(this);
    this.onCountChange = this.onCountChange.bind(this);
  }

  componentDidMount() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  componentDidUpdate() {
    // eslint-disable-next-line
    console.log('logger', this.state, this.props);
    document.title = `Selected - ${this.state.selected}`;
  }

  onProductChange(e) {
    this.setState({selected: e.target.value});
  }

  onOrder() {
    const {count, selected} = this.state;
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  }

  onCountChange(e) {
    this.setState({count: e.target.value});
  }

  render() {
    return (
      <div>
        <div>
          <b>Product: </b>
          <select onChange={this.onProductChange}>
            <option value="Purple Haze">Purple Haze</option>
            <option value="Amnesia">Amnesia</option>
            <option value="GoGreen">GoGreen</option>
          </select>
        </div>
        <div>
          <b>Count: </b>
          <input
            type="number"
            min={0}
            value={this.state.count}
            onChange={this.onCountChange}
          />
        </div>
        <div>
          <button onClick={this.onOrder}>Order</button>
        </div>
      </div>
    );
  }
}

export default Menu;

```
So we only changed this piece.
```js
  onOrder() {
    const {count, selected} = this.state;
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  }
```

Just one line of code fixes our issue.

Let's dive deep and understand what happens here.

#### The "this" is mutable

```js
  onOrder() {
    setTimeout(() => {
      alert(`You ordered ${this.state.count} ${this.state.selected}`);
    }, 3000);
  }
```
Let's take a look at this buggy code first.

We select a product - "GoGreen". State changes to it. Component re-renders.  
`this.state.selected === "GoGreen"`  
Click the order button. The `onOrder` method fires.  
`setTimeout` starts. 3 seconds pass. The callback is executed.  
We read `this.state.selected` and get "GoGreen".

Here everything is working great. Now let's see how the bug happens.

We select a product - "Amnesia". State changes to it. Component re-renders.  
`this.state.selected === "Amnesia"`  
Click the order button. The `onOrder` method fires.  
`setTimeout` starts. **Before** 3 seconds pass, we select another product - "GoGreen".  
State changes to it. Component re-renders.  
`this.state.selected === "GoGreen"`  
3 seconds pass. `setTimeout` callback runs. We read `this.state.selected` and get "GoGreen".  
However this time we clicked the order button when we selected the "Amnesia" product.  
The problem here is the `this`. It changes during the scope of the `onOrder`.

##### Solution

Now let's take a look at the solution.

 ```js
   onOrder() {
     const {count, selected} = this.state;
     setTimeout(() => {
       alert(`You ordered ${count} ${selected}`);
     }, 3000);
   }
 ```
 
 We select a product - "Amnesia". State changes to it. Component re-renders.  
 `this.state.selected === "Amnesia"`  
 Click the order button. The `onOrder` method fires. 
 We read the `this.state.selected` and assign it to the new variable `selected` in the function scope.  
 `selected === "Amnesia"` 
 `setTimeout` starts. **Before** 3 seconds pass, we select another product - "GoGreen".  
 State changes to it. Component re-renders.  
 `this.state.selected === "GoGreen"`  
 3 seconds pass. `setTimeout` callback runs. We read the `selected` of the function scope not from the `this`. And get "Amnesia".  
The `this` changed/mutated but function scope and variables in it were still the same.

So we solved the `this` problem by function scope.

#### 2 Dimensions

One way that I find easy to think about the `this` and function scope, is to think about them like dimensions.

![dimensions](https://i.imgur.com/M3HJ0lY.png)

We have these 2 dimensions where we store our data.

The `this` can change during the scope.

![dimensions](https://i.imgur.com/gFhXEH1.png)

So you need to be aware of the 2 dimensions where our data reside. And how they interact. 


### Fucking bring hooks already!

Fine! Fine...

So you heard about this next hot thing that's called hooks.  
Now you want to refactor your `Menu.js` component to use hooks.  
You were going to refactor it anyway because of performance issues in branch 3, so lets refactor straight to hooks.


Create a new simple functional component `MenuFC.js`.

```
import React from 'react';

const MenuFc = () => {
  return (
    <div>
      <div>
        <b>Product: </b>
        <select>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <button>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;
```

So plain and beautiful. Simple function that returns some jsx.  

Now what do you think, wouldn't it be nice if we could do something like this?

```
import React from 'react';

const MenuFc = () => {
  const state = 'Purple Haze';
  
  return (
    <div>
      <div>
        <b>Product: </b>
        <select value={state}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <button>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;
```

Wow, our state to be a simple variable in function scope. That's crazy man!  

But we need to somehow be able to change it, right? Otherwise it's not useful as state.  
Imagine if we had `setState` as simple function in scope.

```
<select onChange={setState} value={state}>
  <option value="Purple Haze">Purple Haze</option>
  <option value="Amnesia">Amnesia</option>
  <option value="GoGreen">GoGreen</option>
</select>
```

What do you think? It's so nice and clean.  
So how do we accomplish this with hooks?

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = (e) => {
    setSelected(e.target.value);
  };

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <button>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

I know what you are thinking. "I liked you at first, but now, what kind of black magic is this?"  
```js
const [selected, setSelected] = useState('Purple Haze');
```

Please just give me a moment. It is a simple [ES6 Array Destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring).  
You learnt the big and verbose class syntax, surely this tiny syntax won't hurt you.

#### Now let's look at benefits

Our `selected` and `setSelected` are just plain variables in our function scope.  

`useState` function imported from `react` gets one argument - the initial state.
It returns an array.  
The first element is the value of our state.  
The second is a function to change the value.  

We use that function to create a callback to execute when a user selects different product.

So take a look at this beauty once more.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = (e) => {
    setSelected(e.target.value);
  };

  return (
    <div>
      <div>
        <b>Product: </b>
        <select value={selected} onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <button>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

"But you are creating a new callback function on each render, it's bad for performance!".  
Some of you might say.  
Well it turns out... [No.](https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render)

[Here is what react official docs say about that.](https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render)

> No. In modern browsers, the raw performance of closures compared to classes doesn’t differ significantly except in extreme scenarios

Moreover

> Hooks avoid a lot of the overhead that classes require, like the cost of creating class instances and binding event handlers in the constructor.

So if we just separate out politics from these sentences, the raw meaning strictly equals  

_As React components classes do so much shit that if we just throw them away and use functions,  
we get a lot of performance benefit compared to which creating a new callback function at every render at most cases is nothing_

And you can find some performance tips and tricks mentioned there. We'll dive into these later.

Now let's add the ordering functionality.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = (e) => {
    setSelected(e.target.value);
  };

  const onOrder = () => {
      setTimeout(() => {
        alert(`You ordered ${count} ${selected}`);
      }, 3000);
    };

  return (
    <div>
      <div>
        <b>Product: </b>
        <select value={selected} onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```
Again. Simple as that, just a plain function.  
Notice in this case we don't need to put the `onOrder` in the component scope.  
We can declare it outside and use it inside the component by passing arguments.

```js
const onOrder = (count, selected) => {
  setTimeout(() => {
    alert(`You ordered ${count} ${selected}`);
  }, 3000);
};

```

Here is another great thing about hooks. You can have as many of them as you'd like.  
Let's implement the count.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = (e) => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = (e) => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input
          type="number"
          min={0}
          value={count}
          onChange={onCountChange}
        />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

What a beauty! And we don't have any `this` problems.  
No bindings! No async bugs! Now it's just a plain function and only a scope.

![One Dimension Only](https://i.imgur.com/aqY05Tz.png)

Now let's get acquainted with the next hook.
Turn to the next branch.

### Side effects!

Where did we perform side effects in class components?  
Lifecycle methods.

To perform side effects in functional components now we have `useEffect`.

In our `Menu.js` class component we have a side effect for changing our document title.  
Here is how we do it in `MenuFC.js`

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = e => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = e => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  useEffect(() => {
    document.title = `Selected - ${selected}`;
  });

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input type="number" min={0} value={count} onChange={onCountChange} />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

`useEffect` accepts a function as an argument.  
There we perform our side effects.  
It runs on every render.
It behaves
> as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

https://reactjs.org/docs/hooks-effect.html

We also had a logger in our class component. Let's add it.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = e => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = e => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  useEffect(() => {
    // eslint-disable-next-line
    console.log('logger', selected, count);
    document.title = `Selected - ${selected}`;
  });

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input type="number" min={0} value={count} onChange={onCountChange} />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

Everything looks great right? Before we go deeper one thing...

### useEffect is a whole new concept

Do not think of `useEffect` as a new lifecycle method.  
It's a whole new concept.

It's not a lifecycle method, it behaves similar to them.

`useEffect` timing is different.  

https://reactjs.org/docs/hooks-reference.html#timing-of-effects

##### Old problems

In our class component we had a few issues.  
As state changes our component re-renders.  
`componentDidUpdate` fires and `document.title = this.state.selected` was running,  
even though we changed only the count and not the title. With classes we'd put some if check.

Also we wanted to make our logger functionality reusable. With classes we'd make a HOC.

The same problems we have now here with our `useEffect` hook.  
At the moment it's as bad as lifecycle methods.

Let's see how it's actually better.  
Turn to the next branch.

### It's useEffect not effects

Take a look at this code.

```
useEffect(() => {
    // eslint-disable-next-line
    console.log('logger', selected, count);
    document.title = `Selected - ${selected}`;
});

```

While it may seem okay, conceptually it is not.

In the callback function, the 2 lines of code have different concerns.  
They do stuff unrelated to each other.  
We need better separation of concerns.

So in fact this is much more better.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = e => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = e => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  useEffect(() => {
    document.title = `Selected - ${selected}`;
  });

  useEffect(() => {
    // eslint-disable-next-line
    console.log('logger', selected, count);
  });

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input type="number" min={0} value={count} onChange={onCountChange} />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

### Deps

Now we need our `document.title` effect run only when the `selected` state changed.  
In usual `componentDidUpdate` you'd do some `prevProps` comparisons and so on.

Guess what? `useEffect` now will do it for you! You just need to tell it what it needs to check.  
How do we tell it what variables to check? Just pass a second argument to it.

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

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = e => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = e => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  useEffect(() => {
    document.title = `Selected - ${selected}`;
  });

  useEffect(() => {
    // eslint-disable-next-line
    console.log('logger', selected, count);
  });

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input type="number" min={0} value={count} onChange={onCountChange} />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

Yes simple like that. `useEffect` gets second argument. It's an array.  
In that array you put any variable which change should trigger the effect.  
In case those variables don't change. The effect will not run.  

Just add another `console.log` to that effect and you will see it now runs only when the `selected` changes.

### Re-usable hooks

Let's dive right into coding.

We create a new `hooker.js` file.

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

// updateDocumentTitle name is bad the custom hook name should start with "use"
export const useDocumentTittle = title => {
  useEffect(() => {
    document.title = title;
  }, [title]);
};

export const useLogger = (...args) => {
  useEffect(() => {
    // eslint-disable-next-line
    console.log('logger', ...args);
  });
};

```

Then we do this in our `MenuFC.js`

```
import React, {useState} from 'react';
import {useDocumentTittle, useLogger} from './hooker';

const MenuFc = () => {
  const [selected, setSelected] = useState('Purple Haze');
  const onProductChange = e => {
    setSelected(e.target.value);
  };

  const [count, setCount] = useState(0);
  const onCountChange = e => {
    setCount(e.target.value);
  };

  const onOrder = () => {
    setTimeout(() => {
      alert(`You ordered ${count} ${selected}`);
    }, 3000);
  };

  useDocumentTittle(`Selected - ${selected}`);
  useLogger(selected, count);

  return (
    <div>
      <div>
        <b>Product: </b>
        <select onChange={onProductChange}>
          <option value="Purple Haze">Purple Haze</option>
          <option value="Amnesia">Amnesia</option>
          <option value="GoGreen">GoGreen</option>
        </select>
      </div>
      <div>
        <b>Count: </b>
        <input type="number" min={0} value={count} onChange={onCountChange} />
      </div>
      <div>
        <button onClick={onOrder}>Order</button>
      </div>
    </div>
  );
};

export default MenuFc;

```

That's right!
Now we can use any of these hooks in any **React Functional Component**.

That's how simple sharing logic can be.

### Some general rules for hooks

Remember that custom hooks should be named as native hooks. The **use** word should be **used**.

Hooks cannot be in conditions. But you can have conditions in your `useEffect` callback

And so on... You definitely should check [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks) 

### To be continued...

And that's it for hooks intro!  
Soon I'll dive deeper into more specific cases...  
So keep up with me!
See you soon!