Class Components Vs Function Components
Class Components
Back in the days React components were classes, and the components were following an imperative approach. And with the introduction of hooks, react has moved towards a declarative approach. While it has become easier to create the same component with hooks in significantly less code compared to class components, it has also become way easier to write buggy, slow and unreadable hard-to-understand bad code. So it has become more important than ever to understand how react works.
In the class components, the UI code is in the render method of the class, and the states, functions, event handlers everything was outside the render method. They were properties or methods of the component class. To re-render a component, it just needs to call the render method, and no function or state variables will be re-created or re-instantiated.
// Simple React class component example
import React, { Component } from 'react';
class Counter extends Component {
// State is defined as a property of the class
state = {
count: 0,
};
// Event handler is a method of the class
increment = () => {
this.setState({ count: this.state.count + 1 });
};
// UI code is inside the render method
// Calling this method wont re-create increment method or the state properties of the class
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;
Function Components
But now that render method has become the entire component. All the states, state-modifier functions, event handlers, life-cycle hooks/functions, everything lives inside that component function. Anytime that component needs to be updated or re-rendered, the component function is executed.
But function component is just a javascript function. When a javascript function gets called again, all of its arguments and internal variables/properties, everything get re-created and re-defined. So in the react components all the props, all the functions defined inside the component, all the variables including states, state-modifier function, prop restructured value, everything gets re-created and re-defined.
import React, { useState } from 'react';
// The entire function body runs on every render,
// so all variables and functions defined here are re-created each time
function Counter() {
// State and state-modifier function are created on every render
const [count, setCount] = useState(0);
// This function is re-created on every render
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default Counter;
But then... wouldn't that trigger infinite re-renders if everything is always being re-created (changed)? Yes, it would. That's where hooks come into the picture.