React Hooks Basics

Hindu Sreeni
FORMCEPT
Published in
6 min readOct 10, 2019

Everything you need to get started with Hooks

React before hooks

ReactJS is one of the most popular JavaScript front-end libraries for building reusable UI components. It is efficient and flexible. React components let you split your UI into reusable pieces and design each in isolation. Generally, React components can be categorized into two types:

  • Class components
  • Functional components

With this quick overview of React, let’s get started! In the context of this blog, I will be assuming that you are already familiar with the fundamentals of React.

Class Component

In React, class components can maintain their state and re-render the components and all their children whenever the state changes. They can also support all the React lifecycle methods. Class components make use of ES6 class and extend the Component class in React. These are also known as smart components.

import React, { Component } from “react”;class MyComponent extends Component {constructor(props){super(props);this.state = {greeting: “Hello”;}}render() {return (<div><p>{this.state.greeting} {this.props.name}</p></div>);}}export default MyComponent;

Functional Components

Functional Components are typically basic javascript functions or arrow functions. They are primarily used only for presentation. They don’t maintain state or support lifecycle methods and are generally referred to as the dumb components.

import React from “react”;const MyComponent = props => (<div><h1>Hello, {props.name}</h1></div>);export default MyComponent;

A Few Drawbacks in the System:

Reusing Logic:

Whenever the code or the logic needs to be reused, we introduce the concept of Higher Order Components (HOC) or RenderProps. But, the downside is that the application needs to be restructured whenever we use them. Otherwise, the application is likely to end up in the Wrapper hell.

Giant Components:

You must have come across a situation when you started with a small and simple component that later turned out to be huge and complex and became harder to maintain and split, simply because the stateful logic was all over the place.

Class Components:

Though I have been working with React for a while now, classes have been always confusing. Either I forget to bind the event handlers or find it difficult to identify when to use class components as opposed to functional components. Sometimes, you need to convert functional components into class components only to keep track of one state or in most of the cases we end up creating class components to be on the safer side.

All of the above three problems are related. For instance, when we are trying to solve the wrapper hell by introducing more logic into the component, it results in the component turning out to be huge. On the other hand, if you split the code and try using them as smaller components, it leads to nesting and wrapper hell. Classes are confusing in both cases. The above three issues, therefore, are not the actual problems, but various symptoms of a common problem.

React doesn’t provide a stateful primitive than a class component.

This is where Hooks come to the rescue. Hooks are the newest addition in React 16.8. Hooks are functions that let you access and manage React state and life cycle features from functional components. Hooks don’t work inside classes, instead, they let you use React without classes!

  • Hooks allow you to reuse stateful logic without changing your component hierarchy.
  • Hooks let you split one component into smaller functions based on which pieces are related (such as setting up a subscription or fetching the data), rather than forcing a split based on lifecycle methods.
  • Hooks let you use several more of React’s features without classes.

Uses of Hooks:

  • Hooks allow you to write organized code, increase readability, encourage better coding practices and boost the performance of functional components.
  • One major advantage of using Hooks is that when class-based and function-based components are converted to backward-compatible JS code, the size of the converted class component is significantly more than a functional component. As a result, the webpack chunk-size increases, which can affect the performance. Hooks solve this problem by drastically reducing the size of the chunk.

useState

useState lets you use local state within functional component.

Declare state variable:

import React, { useState } from ‘react’const displayAge = () => {const [age, setAge] = useState(0);return <div> Age = {age} </div>}//output -Age = 0

In this example, the variable age is the state variable and setAge is the method to be called to update the state. useState takes in the initial state for the variable and returns an array of state and the function that allows us to change the state.

Update state variable:

import React, { useState } from ‘react’const displayAge = () => {const [age, setAge] = useState(0);const handleClick = () => setAge(age + 1)return (<div>My age is {age}<div><button onClick={handleClick}>Get older! </button></div></div>)}

Multiple state variables:

Multiple state variables can be used and updated from the functional component. State variables can hold objects and arrays just fine, so you can still group the related data together. However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it.

import React, { useState } from ‘react’const displayAge = () => {const [age, setAge] = useState(20);const [siblingsCount, setSiblingsCount] = useState(1);const handleClick = () => setAge(age + 1)const handleSiblingsNum = () => setSiblingsNum(siblingsNum + 1)return (<div><p> My age is {age}</p><p>I have {siblingsNum} siblings</p><div><button onClick={handleClick}>Get older! </button><button onClick={handleSiblingsNum}>More siblings!</button></div></div>)}

Object state variable :

useState also takes in objects. You could also set an object as initial state for useState.

() => {const [state, setState] = useState({ age: 19, siblingsNum: 4 })const handleClick = val =>setState({…state,[val]: state[val] + 1})const { age, siblingsNum } = statereturn (<div><p>Today I am {age} Years of Age</p><p>I have {siblingsNum} siblings</p><div><button onClick={handleClick.bind(null, ‘age’)}>Get older!</button><button onClick={handleClick.bind(null, ‘siblingsNum’)}>More siblings!</button></div></div>)}

Functional setState:

The useState’s update function can also take in function similar to that of setState.

() => {const [count, setCount] = useState(0);return (<><p>Count value is: {count}</p><button onClick={() => setCount(0)}>Reset</button><buttononClick={() => setCount(prevCount => prevCount + 1)}>Plus (+)</button><buttononClick={() => setCount(prevCount => prevCount — 1)}>Minus (-)</button></>);}

useEffect

The Effect Hook lets you perform the side effects and allows you to use lifecycle methods in functional components. To be more precise, it can perform the actions of componentDidMount, componentDidUpdate and componentWillUnmount lifecycle methods.

The syntax of useEffect ,

useEffect (( )=> {console.log(“Inside useEffect”)}, [ ] )

useEffect receives two parameters,

  • function
  • array( optional )

In short, useEffect invokes that function based on the second parameter. Whenever the value of the state changes, the component will be re-rendered and the execution of useEffect will be determined by the values in the array. If any of the variables’ state which is inside the array changes, the useEffect will be called in the re-render. The value of the variable’s state will be compared to its previous state. If the values are different, the useEffect will be executed.

const [count, setCount] = useState(0);useEffect(() => {console.log(`I have been clicked ${count} times`);}, [count]);return (<div><button onClick={() => setCount(count + 1)}>Click me!</button></div>);In the above case the output will be,// I have been clicked 0 times// I have been clicked 1 times// I have been clicked 2 times

Every time the value of count changes, the component will be re-rendered and useEffect will be called. This is similar to the functioning of the ComponentDidUpdate.

When the array is empty,

useEffect(() => {console.log(`I have been clicked ${count} times`);}, []);// I have been clicked 0 times

If we leave the array empty after the first render, useEffect will be called and during subsequent re-renders there will be no value in the array to compare and hence, there will be no change. Therefore it won’t be executed in the re-render. This is similar to the functioning of componentDidMount.

When the second parameter is not given,

useEffect(() => {console.log(`I have been clicked ${count} times`);});// I have been clicked 0 times// I have been clicked 1 times// I have been clicked 2 times

In this case, the function will be invoked in every re-rendered. No value is passed and therefore no comparison is made.

To understand in depth about hooks and create your own custom hooks, checkout

--

--