React JS Understanding and Utilizing the potential of useEffect Hook
React manages changes in the state objects which run asynchronous updates in the functional components after the
DOM gets updated and this does not obstruct the DOM operations, unlike class components that do.
The useEffect hook is called after the component is rendered and also gets called when
the components re-renders or state object is modified or after components are unmounted.
So the process of triggering action after the components renders or specify state object gets modified is termed as side effects.
You can import useEffect hook in import { useEffect } from 'react'
the same way you would do with the useState
hook. And to use this hook you need to pass the first parameter which is a function and the second parameter which is optional it is also called as dependency parameter
as it is executed when the value of a particular state object gets updated.
useEffect(() => { console.log(`Renders everytime`) });
In the above example, When the second parameter has not been specified the effect will
be called every time the state value within the functional component gets updated.
useEffect(() => { console.log(`Renders once`) }, [] );
When you provide value for the second parameter as an empty array then the effect will be called only once when the component is first rendered and will not be called during any component update.
useEffect(() => { console.log(`List updated`) }, [ state_var ] );
Within the array [ state_var ]
you can provide a state variable and the useEffect will watch the changes on that state variable. If it detects changes then react will trigger the useEffect hook. You can pass multiple state variables side-by-side within the array.
Caution
Don’t try to update the state within useEffect as it may lead to continuous recursive loops and then your performance will be largely affected.
In this post, I’ll teach you how to properly utilize and work with useEffect hook by using a Todo example.
Creating Todo Component
In src\components\todos.js
import React, { useEffect, useState } from 'react' export default function Todos() { const [list, setList] = useState([ 'Apple', 'Orange', 'Mango' ]); const remove = ( index ) => { if( list[index] ){ list.splice( index, 1 ) } setList([...list]) } // called only once during first render useEffect(() => { console.log(`Todos Component : First Render`) }, [ ] ); // called on every re-render useEffect(() => { console.log(`Todos Component : Renders Everytime`) }); // called when the list changes useEffect(() => { console.log(`Todos Component : Renders when list state gets updated`) }, [ list ] ); return ( <div> <input type="text" onBlur={ ( e ) => ( e.target.value !== '' )? setList([...list, e.target.value ]) : '' } defaultValue="" /> { ( list.length ) ? list.map( ( item, index ) => { return ( <TodoItem key={index} index={index} name={item} remove={remove} /> ) } ) : null } </div> ) }
Here the state objects [list, setList]
hold the list of items to be completed. The function remove
will delete the index from list
the state object.
Here a bunch of list items is displayed and they are iterated over a TodoItem
a component that holds a single list item.
In src\components\todos.js
export function TodoItem( props ) { // gets called only on component mount and not on unmount useEffect(() => { console.log(`TodoItem Component : Loaded `) // gets called when component is removed return () => { console.log(`Running cleanup...`) } }, [ ] ); return ( <li>{ props.name } - <button type="button" onClick={ () => props.remove( props.index ) } >Remove</button> </li> ) }

the output of react js useEffect hook on Todos Components
The component TodoItem
renders the single list item. All the methods as passed from the parent component such as
name
, index
and remove()
function.
You can also run a function when a component gets removed or unmounted just by returning a function inside the
first parameter function of useEffect hook.
Handle Nested Object value updates
Suppose you have a form variable of state object which is an object of key-value pairs you can also trigger useEffect hook on
the particular key.
export function MyComponent( props ) { const [form, setForm] = useState({ name : '', age : '', }); const [canVote, setCanVote] = useState( null ); useEffect(() => { console.log('component loaded') } ); useEffect(() => { console.log('form age value changed') setCanVote( ( form.age >= 18 )? true : false ) }, [ form.age ] ); return ( <> <div> <label>Name</label> <input type="text" onChange={ ( e ) => setForm( { ...form, name : e.target.value } ) } value={form.name} /> </div> <div> <label>Age</label> <input type="number" onChange={ ( e ) => setForm( { ...form, age : e.target.value } ) } value={form.age} /> { canVote===true ? <div>Yes you can vote</div> : <div>No you cannot vote</div> } </div> </> ); }

Output on Triggering useEffect Hook on Nested object values
Here the useEffect on [ form.age ]
will be called only when the age value gets updated.
Watch Video
So here I have covered all the concepts and the ways how you can utilize the potential of useEffect hook. And here is the link to Github Repository.
See you in the next post.




