React Hooks

React Hooks got introduced in 16.8. Reacts Hooks allow us to use state and other react feature without writing a class.

Note: We can not call hooks inside loop or condition. Hook can only be use with Functional Components and because of this reason class components loosing its charm.

As part of this blog, we are going to read about important hook use as part of React application:

  • useState
  • useReducer
  • useEffect
  • useRef
  • useContext
  • useParams

Below are some of the hooks examples:

useState

useState helps us to initialize variable and update its state.

Always call useState at the top of the component to initialize variable.

Syntax:

Below is the useState example to initialize count to zero.

import React, { useState } from 'react';

export default function App() {
const [count, setCount] = useState(0);

return (
<div>
<p>Number of Clicks = {count}</p>
<button onClick={() => setCount(count + 1)}>Counter</button>
</div>
);
}

setCount() function will only update the view. In JavaScript it will print old value.

const [name, setName] = useState('John');
setName('imran')
console.log(name); // John

useReducer

useReducer is used in case of objects/array and can be used to manage multiple state transitions.

In comparison of useState, useReducer allow us to update state outside of component also.

In strict mode, React will always reducer and initialize functions twice. It will not break code or anything.

Syntax

import { useReducer } from 'react';

function reducer(state, action) { }

function App() {
const [state, dispatch] = useReducer(reducer, { age: 42 });

dispatch({ type: 'INC' }); // To trigger reducer
}

useReducer returns an array of initial value and update value using dispatch function.

dispatch() allow us to pass current state to reducer and get updated state in return.

Example

Below is the basic example to increment number by 5.

import { useReducer } from 'react';

function reducer(state, action) {
if (action.type === 'INC_BY_5') {
return {
number: state.number + action.inc
};
}
}

export default function App() {
const [count, dispatch] = useReducer(reducer,{number: 0});

function incrementByFive() {
dispatch({ type: 'INC_BY_5', inc: 5});
}

return (
<>
<button onClick={incrementByFive}>Increment</button>
<p>Count = {count.number}</p>
</>
);
}

OUTPUT

Example:

Below is the best example of useReducer to increment and decrement number.

import { useReducer } from 'react';

function reducer(state, action) {

if (action.type === 'INC') {
return {
number: state.number + 1
};
}
if (action.type === 'DEC') {
return {
number: state.number - 1
};
}
if (action.type === 'INC_BY_10') {
return {
number: state.number + action.inc
};
}
throw Error('Error !!!!');
}

export default function App() {
const [count, dispatch] = useReducer(reducer,{number: 0});

return (
<>
<button onClick={() => {
dispatch({ type: 'INC'})
}}>
Increment
</button>
<button onClick={() => {
dispatch({ type: 'DEC' })
}}>
Decrement
</button>
<button onClick={() => {
dispatch({ type: 'INC_BY_10' , inc: 10 })
}}>
Increment By 10
</button>
<p>Count = {count.number}.</p>
</>
);
}

OUTPUT

useEffect

useEffect helps us to synchronize with external system, update DOM on change of state, timers, etc.

useEffect accepts two below arguments:

useEffect(<function>, <dependency>);

<function> to have code snippet logic.

<dependency> decides when to execute function.

Below useEffect will always run on every render

useEffect(() => {

});

Below useEffect will get execute once on first render:

useEffect(() => {

}, []);

Below useEffect will get execute once on first render as well as on the change of declared name and age:

useEffect(() => {

}, [name, age]);

Below is the example of useEffect where updatedCount variable is getting update on change of count variable.

import { useState, useEffect } from "react";

export default function App() {
const [count, setCount] = useState(0);
const [updatedCount, setUpdatedCount] = useState(0);

useEffect(() => {
setUpdatedCount(() => count * 5);
}, [count]); // on change of count it will re-render oe call useEffect

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

OUTPUT

useRef

useRef hook is use to access DOM element directly and works only with functional components. useRef hold mutable value across all component renders.

const customRef = useRef("Hello World !!!"); 

Below is an example to trigger useRef on every render. The view will re-render on change of inputValue, useRef will get call on every render.

import {useState, useEffect, useRef } from "react";

export default function App() {

const [inputValue, setInputValue] = useState("");

const count = useRef(0);
useEffect(() => {
count.current = count.current + 1;
});

return (
<>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<h1>Render Count: {count.current}</h1>
</>
);
}

OUTPUT

useContext

useContext use with useState which helps to maintain state in all nested components.

Syntax:

const CountContext = createContext();

Example:

In below example, <App/> component is calling <Component1/><Component1/> is calling </Component2> and than so on. count value setting as part of context in <Component1/> is getting pass to all nested components as shown below:

import {useState, createContext, useContext } from "react";

const CountContext = createContext();

function Component1() {
const [count, setCount] = useState(100);

return (
<CountContext.Provider value={count}>
<h1>Component 1 - Count: {count}</h1>
<Component2 />
</CountContext.Provider>
);
}

function Component2() {
return (
<>
<h1>Component 2</h1>
<Component3 />
</>
);
}

function Component3() {
const count = useContext(CountContext);

return (
<>
<h1>Component 3</h1>
<h2>Count: {count}</h2>
</>
);
}

export default function App() {

return (
<>
<Component1/>
</>
);
}

useParams

useParams helps us to access current page parameter with the help of React Router.

Syntax:

let { param } = useParams();

Example:

Below is an example to collect parameter as par of URL with the help if <Router/> as shown below:

import React from "react";

import {
BrowserRouter,
Routes,
Route,
useParams,
} from "react-router-dom";

function ProductPage() {
let { param } = useParams();
return <div>Parameter: {param}</div>;
}

function HomePage() {
return <div>Home Page</div>;
}

export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/page/:param" element={<ProductPage />}></Route>
<Route path="/" element={<HomePage />}></Route>
</Routes>
</BrowserRouter>
);
}

OUTPUT

Note: Use below command to install React Router:

Imran Khan, Adobe Community Advisor, AEM certified developer and Java Geek, is an experienced AEM developer with over 11 years of expertise in designing and implementing robust web applications. He leverages Adobe Experience Manager, Analytics, and Target to create dynamic digital experiences. Imran possesses extensive expertise in J2EE, Sightly, Struts 2.0, Spring, Hibernate, JPA, React, HTML, jQuery, and JavaScript.

0