Starting with React Hooks
Tags: codenewbie, react, javascript
Published: 2020-08-03 15:22:30

For just over a year now we've had access to this shiny new feature React Hooks. I'm sure most of us have at least heard of it. 

For me I didn't know what it truly meant or how it compared to what was being done in React prior, honestly. So recently starting to work with React I've been learning about the **Class-based approach** as well as **Hooks**.

## What Are Hooks?

> Hooks are functions that let you “hook into” React state and lifecycle features from function components.

That is straight from [ReactJS.org](https://reactjs.org/docs/hooks-overview.html). Pretty simple, right? Seems so at least.

For me it was good to learn the **Class-based** approach first to understand where React was to move into using **Hooks**. It also made me appreciate **Hooks** that much more as I feel it's a little cleaner and more intuitive - that's personal preference though.

### Class-based approach

When utilizing this approach we would define a `class` component that `extends React.Component`, that way we get access to the React lifecycle methods. This approach in itself has come a long way from the start.

Here's the traditional way we handled **Class-based Components**, again straight from [ReactJS.org](https://reactjs.org):

```jsx
class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
```

Now we can shorten that first bit where we had to call `constructor(props)` and `super(props)` and `this.state = {}` AND we had to _bind_ any event handler we defined. It was just a bit cumbersome.

Here's the shorter **Class-based Component** syntax:

```jsx
class Toggle extends React.Component {
  state = {
    isToggleOn: true
  }

  handleClick = () => {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
```

A little shorter and cleaner, right? All we have to do is just define the `state` object, set our properties and the only other change was converting `handleClick` into an arrow function - that way `this` will still reference our component.

### **Side Note: Functional Components**

**Functional Components** are in a simple explanation just function that will return some _jsx_. A 'dumb component' if you will. They do not need to know state and just receive **props** to render their _jsx_ correctly.

```jsx
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
```

Quite simple.

### Hooks

When utilizing **Hooks** our **Functional Components** take over the role our **Class-based Components** had. **Hooks** _will not_ work inside a `class` - we _must_ use our **Functional Components**.

For reference in the upcoming examples here is the previous `Toggle` Component refactored to use React Hooks:

```jsx
const Toggle = () => {
  const [isToggleOn, setIsToggleOn] = useState(true)

  const handleClick = () => {
    setIsToggleOn(!isToggleOn)
  }

  render() {
    return (
      <button onClick={handleClick}>
        {isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
```

## Commonly Used Hooks

In the **Class-based** approach we would have access to certain _lifecycle methods_ that allowed us to update our application at the right times and perform operations at the right times.

### `useState()`

This Hook took over for `setState()` in **Class-based components**. 

```jsx
const [isToggleOn, setIsToggleOn] = useState(true)
```

This `useState()` allows us to simultaneously set the state of `isToggleOn` with the argument provided to the method - here that is `true` - as well as get back a setter to change that piece of state in the future - here it's called `setIsToggleOn`.

The 'set' part of that _is convention_ to make it clear that **this function** will **set** the piece of state called **isToggleOn**.

Call `useState()` for as many pieces of state you have in different calls and you'll have setters for each piece of state. It can make it much more clear what we're trying to change.

```jsx
// Class-based setState()
handleClick = () => {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }
// Hooks
const handleClick = () => {
    setIsToggleOn(!isToggleOn)
  }
```

It's shorter and arguably more intuitive than having to type out all of the **Class-based** way.

### `useEffect()`

Now when we needed to fetch data, setup subscriptions or explicitly change DOM elements we would use the lifecycle methods `componentDidMount`, `componentDidUpdate` and `componentWillMount`.

With `useEffect` we basically have those three methods wrapped up inside of just his one. Definitely check out the [docs on useEffect](https://reactjs.org/docs/hooks-effect.html) as it goes way more in depth and gives you context on the best practices on how to split your logic.

Here, since I'm still reading those docs and wrapping my own head around this, I'm only going to provide a simple example that involves data fetching. This example is from a small practice project I recently did:

```jsx
// The 'api.index()' method used in the following block of code that makes the call for data
export default {
  async index() {
    const res = await fetch('https://my-json-server.typicode.com/Claim-Academy-JS/products/products')

    return await res.json()
  }
}
```

```jsx
  // Class-Based
  async componentDidMount() {
    const products = await api.index()
    this.setState({ filteredProducts: products, products })
  }

  // Hooks
  useEffect(() => {
    const fetchData = async () => {
      const products = await api.index()
      setFilteredProducts(products)
      setProducts(products)
    }

    // If the data hasn't been fetched then make the api call
    if (products.length === 0)
      fetchData()
  })
```

So in our **Class-based Components** we would use `componentDidMount` to ensure _before_ we made an attempt to fetch data the component itself was rendered _and then_ we would update it on receiving our data from the server. This lifecycle method runs just once as the Component only mounts once in its lifecycle.

`useEffect` will run when the Component mounts, each time it updates and right before it unmounts. That is why there's a piece of logic to ensure we don't attempt to re-fetch the data each time this Component updates. 

## Custom Hooks

**Custom Hooks** are basically what they sound like - your own defined Hooks that you can design to help you with application-specific tasks or maybe tasks you've found yourself doing a bunch and could be streamlined having your own Hook for that task.

Once again, Hooks are something I've been working with just a week or so at this point. I'm not the one to tell you how to develop your own Custom Hook because I haven't tried myself yet! 

The [docs on Custom Hooks](https://reactjs.org/docs/hooks-custom.html) do a good job explaining and have a great example to show a proper use case. It made sense to me reading but I'm not going to try and rehash that here as I haven't put it in practice yet.

## There Is Much More to Hooks...

... than I can tell you! I'm only beginning to scratch the surface of how to use Hooks to their full potential.

Not to mention the **Custom Hooks** I've yet to experiment with if you check out the [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html) you'll see even more out-of-the-box Hooks like `useContext`, `useReducer`, `useLayoutEffect` and more!

These examples I have were just the first Hooks I've put to use and made me see the benefit and potential of utilizing Hooks moving forward.