What did React Hooks bring to React?

With the version 16.8, React introduced React Hooks

To begin with, let’s talk about why React needed hooks? 

1- Functional components (used to be called stateless components) were preferred for the performance but they had the problem of state management. As it used to be called, they were “stateless”.

2- Class components can get very complicated with different interpretation of ‘this’, using life cycles correctly, binding issues etc.

3- React wanted to stay relevant with the ahead of time compilation methods and be one of the building blocks of future technologies.

4- Separating different logics in the same function (for example in componentDidMount). 

5- It was hard to share stateful logic between components.

How Hooks solve these problems?

Before if your component requires state, you had no other choice than using class components. Hooks brought state to the functional components which made class components arbitrary and unnecessary.

One of the cool things about this release, it doesn’t break your existing code. Your project can include both functional components with hooks and class components simultaneously. This means, you don’t have to hurry to rewrite your project to be able to use hooks. This doesn’t have to be an instant change. You can start building your new components with hooks and with time you can pay off your technological debt if you prefer.

I want to mention 2 of the most common hooks, for the rest you can look at the official react documentation for the Hooks API Reference

useState

This hook returns a stateful value and a function to update it.

const [color, setColor] = useState('black');

In this example, black is the initial value for the color.

About this syntax, we are naming and destructuring the array returned by useState. Using [stateName, setStateName] format is preferred. StateName being whatever you want to call your variable.

If you want to see how to use it without destructuring in the beginning you can look at below example. Keep in mind that this is just for explaining, it is not recommended to use.

const colorState = useState('black');
const color = colorState[0];
const setColor = colorState[1];

useState hook can take string, array, object, boolean, null, number. Also it is possible to use more than one useState hook in your component.

const [color, setColor] = useState('black');
const [count, setCount] = useState(0);

Also since you can also use object as a value, you can group your relevant data in one hook as well.

const [person, setPerson] = useState({ 
  name: 'Oz',
  age:30,
  profession: 'Software Developer'
});

When we want to change the state, we just use

setColor('blue');
setCount(count+1);
setPerson({name: 'John', age:25, profession: 'Salesman'});

Note: useState doesn’t merge the new state with the previous one, it replaces it. If you want similar behaviour as setState in class components, you can use it like;

const [state, setState] = useState({});
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

useEffect

Accepts a function that contains imperative, possibly effectful code.

Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.

Instead, use useEffect. The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React’s purely functional world into the imperative world.

By default, effects run after every completed render, but you can choose to fire them only when certain values have changed. Which is a great optimization for performance by blocking unnecessary re-renders.

You have the option to return a function in your useEffect hook, which is interpreted as cleanup function. It executes before rendering to make sure there is no remains from previous render and after component renders.

This makes it suitable for the many common side effects, like setting up subscriptions and event handlers, because most types of work shouldn’t block the browser from updating the screen.

Now let’s make a counter component that combines what we learned from useState and useEffect hooks!

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

const CounterComponent = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log('count is increased!');

    return () => {
      // whatever you want to clean
    };
  }, [count]);

  return (
    <div>
      <p>Count is {count}</p>
      <button onClick={() => setCount(count+1)} />
    </div>
  );
};

export default CounterComponent;

Here in our component, we create a count state with the initial value 0.
We have a paragraph that tells us the value of count and a button to increase the count value every time it is clicked.
Also we used useEffect hook to log to the console every time the state of count is changed.

Just as useState, useEffect hook can also be called multiple times in a functional component. It is the correct place to make your API calls.
Note that: For better performance, you should separate each API calls and/or irrelevant logics in to different useEffect hooks.

Custom Hooks
With React Hooks, you don’t just get the hooks React provides for you. It also gives you chance to create your own!

One thing you should understand about custom hooks, it is not for sharing state between components. It is for sharing stateful logic!

For more information about Custom Hooks, you can check the official documentation from here.

Rules of Hooks
There are 2 key rules of hooks.

1- Always call your hooks at the top level of your component. Which mean do not call hooks in nested functions or conditionally etc.

2- Only call hooks from functional components or your custom hooks. Not in normal Javascript functions.

React released an ESLint plugin called eslint-plugin-react-hooks that enforces these two rules. You can add this plugin to your project if you’d like to try it:

This plugin is included by default in Create React App.

I hope you liked reading this post, I tried to summarize the hooks for you.

Post by Oz

2 thoughts on “What did React Hooks bring to React?

  1. Pingback: Redux with Typescript - Ozan Oz

Leave a Reply

Your email address will not be published. Required fields are marked *