React Hooks Instead of Class Components in React.

What are Hooks in React?

Seeta Ram Yadav
Webtips
5 min readJun 6, 2020

--

React 16.8 provides new API which lets you use state and other React features, for example, handling any side effects without writing a class.

Before React 16.8 version there was no option to use states in our functional components.

* Functional components are easy to understand because when you write the functional components you will have less code and also you don’t have to deal with this keyword. With functional components you can write the code at one place which you need to update the component after it has mounted and clean the memory for unmounted components states from dom to avoid the memory lick.

  1. To avoid this confusion and boilerplate code.

2. Performance.

3. Reusing logic without using HOC or composition or props drilling approach

Every function, while executing, has a reference to its current execution context, called this

There are 4 different rules for understanding the meaning of this Kyle Simpson has explained it well in his open sourcebook You Don’t Know JS.

So avoiding the use of classes gives the advantage to skip the use of this and avoid some boilerplate code. which is a big win because if you have less code then, you have to read it less and maintain it less. more code more bug :(

Let’s compare the counter and also the window Width example with class and without class.

Counter with hooks.

With the class, we need to declare all our state into our constructor or if you are using it.

class Application extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
width: window.innerWidth
};
}
}

If you don’t want to use the constructor for declaring your state still you can initialize state in your class with the new syntax of classes but you won’t be able to use the props if you need it.

class Application extends Component {
state = {
count: 0,
width: window.innerWidth
};
}

Now let’s declare the state with hooks

function Application() {
const [count, setCounter] = useState(0);
const [windoWidth, setWindowWidth] =useState(window.innerWidth);
}

Let’s use the state to render with class.

render() {
const { count, width } = this.state;
return (
<main className="Counter">
<p className="count">{count}</p>
<p className="window-width">{`Window Width : ${width}`}</p>
</main>
);
}

Render with hooks

return (
<main className="Counter">
<p className="count">{count}</p>
<p class="window-width">Window width: {windoWidth}</p>
</main>

Now let’s add the increment behavior for the counter and window width with class component.

import React, { Component } from "react";
import { render } from "react-dom";

import "./styles.scss";

class Application extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
width: window.innerWidth
};

this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.reset = this.reset.bind(this);
this.handleResize = this.handleResize.bind(this);
}

componentDidMount() {
document.title = this.state.count;
window
.addEventListener("resize", this.handleResize);
}

componentDidUpdate() {
document.title = `Counter: ${this.state.count}`;
}

componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
increment() {
this.setState({ count: this.state.count + 1 });
console
.log(this.state.count);
}

decrement = () => {
this.setState((state, props) => {
if (state.count <= 0) return;
return { count: state.count - 1 };
});
};

reset = () => {
this.setState({
count: 0
});
};

handleResize = () => {
this.setState({ width: window.innerWidth });
};

render() {
const { count, width } = this.state;

return (
<main className="Counter">
<p className="count">{count}</p>
<p className="window-width">{`Window Width : ${width}`}</p>
<section className="controls">
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
<button onClick={this.reset}>Reset</button>
</section>
</main>
);
}
}

render(<Application />, document.getElementById("root"));

Increment counter and resize the window to see how window width getting updated. also when you increment the counter observe the title getting updated.

import React, { useState, useEffect } from "react";
import { render } from "react-dom";

import "./styles.scss";

function Application() {
const [count, setCounter] = useState(0);
const [windoWidth, setWindowWidth] = useState(window.innerWidth);

useEffect(() => {
document.title = "Counter" + count;
}, [count]);

useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [windoWidth]);

const handleResize = () => {
setWindowWidth(window.innerWidth);
};
const increment = () => {
setCounter(count + 1);
console
.log(count);
};

const decrement = () => {
setCounter((state, props) => {
return count - 1;
});
};

const reset = () => {
setCounter(0);
};
return (
<main className="Counter">
<p className="count">{count}</p>
<p class="window-width">Window width: {windoWidth}</p>
<section className="controls">
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</section>
</main>
);
}

render(<Application />, document.getElementById("root"));

Now if you look at close to the above two example. clearlly you can see for handling side effects there are dublication of same code into your componentDidMount and also into componentDidUpdate. In this example page title and window width updation is a side effect, because we are going to update them after component has mounted(rendered) into the Document Ojbect modal. If we don’t do it into our componentDidMount and componentDidUpdate you may find a bug. Also if you look at eventListner in this case handleResize you need to clean it up to avoid memory lick and ideally it should be the responsibility of the same function who is adding this, but into our Class component we will have do it into our componentWillUnmount which is not readable and creating unnecessary confusions. While our functional component are much cleaner because you have all your side-effects and its cleaning part at just one place, in useEffect hooks. so we can use useEffect one sideEffect and create another useEffect for any new side effect and pass all the dependency which will its to trigger when ever that gets change. We can also return an function which will take care of cleaning part and avoid memory lick. in this example look at the useEffect for updating the title and window width .

Now let’s try to understand how it impacts the performance.

Classes are hard for humans, even hard for machines look at the comparison of function vs classes which is been compiled by babel.

Classes component compiled by babel.

Functional Component compiled by babel.

Class components get converted into small peace while class components get converted into big pieces than functional components.

Now the question is what is the problem with this converted class code even though it is big.?

The answer is: It causes the performance issue because at the end of the day these codes need to be rendered on the browser and when there is small peace it can load quickly and render it fast while if it’s big it gonna take some time to load and render on the browser.

Reusing logic and passing down data.

HOC vs custom hooks.

HOC is the concept which a lot of libraries like redux use for sharing the data. How to use HOC in React look at here.

HOC

Custom Hooks

The above example is a comparison of how we can replace HOC with our custom hooks.

--

--

Seeta Ram Yadav
Webtips
Writer for

I am an author, Technology enthusiastic, and a Web Developer with 9 + years of experience in the industries.