React State Management

React State Management

Part - 2

In previous article we have discussed what is react state management and how it is done in react using hooks like useState and useReducer, if you haven't read that post please read it from here and make sure to follow me on hash node if you are interested in articles like this. In this post we will see state monitor hooks like useMemo and useCallback these hooks monitor states of the component and execute the function based on the variables that we provide in the dependency array, confusing? Ok let's look deeper in these hooks with examples to understand it better, before we dive into it make sure you know what is pass by value and pass by reference means which I have explained in my previous article.

useMemo

The useMemo is a react hook that is used in react components that returns stored value of the calculation that is performed previously this will improve performance of your application this value is also known as memoized value. This usually comes from the concept called memoization.This is computer science concept, memoization is a concept used in general when we don’t need to recompute the function with a given argument for the next time as it returns the cached result. In react we use useMemo for similar problem whenever we need to perform a resource heavy function that takes a lot of data we use useMemo so that we execute that calculation only when a particular variable changes but not whenever the component re renders. Here's an example:

Code:

import { useState, useMemo, useCallback } from 'react'


function App() {


 const [numbers] = useState([10,20,30]);


  const total = useMemo( () => numbers.reduce( (acc,n)=> acc+n, 0), [numbers])


  const [names] = useState(["venkata", "satya", "siva"]);


  const sortedNames = useMemo(() => [...names].sort(),[names]); //here sorted names gets executed only when there is a change in names array




  const [count1, setcount1] = useState(0);
  const[count2, setcount2] = useState(0);


  const countTotal = useMemo(()  => count1+count2, [count1,count2]); // this is a bad use of useMemo as it deals with scalers
return (
    <div>
      <button onClick={() => setcount1(count1+1)}> {count1}</button>
      <button onClick={() => setcount2(count2+1)}> {count2}</button>
      <div>Total: {countTotal}</div>


      <div>Names: {names.join(" , ")}</div>


      {/* <div>Sorted Names: {sortedNames.join(" , ")}</div>   */}


      <SortedList List={names} sortFunc={sortFunc}/>

      </div>

  )
}


export default App

In this example sort will be performed only when the names array gets changed as we have mentioned in the dependency array, the syntax of useMemo is

useMemo(() => computation(a, b), [a, b])

Given the same [a, b] dependencies, once memoized, the hook is going to return the memoized value without invoking computation(a, b).

In this example, I have even mentioned that using useMemo for monitoring states of count1 and count2 is bad because it deals with scalers and it is also not a resource-heavy task.

useCallback

useCallback is a hook that is simillar to useMemo but in useCallback we isolate the expensive function, so that the function will only execute whenever there change in dependency variables or the reference to the variable changes, useCallback is generally when you want to pass data to a nested componets or custom hooks where you don't know the implementation as executing these resource heavy functions will break the code. Here is an example of useCallback:

Code:

import { useState, useMemo, useCallback } from 'react'




function SortedList({List, sortFunc}){


  console.log("SortedList rendered"); //this will render every time a button is clicked as the functional component gets rerenderd


  const sortedList = useMemo(() => {
    console.log("running sort"); //this doesn't run even if we click count many times because of useMemo
    return [...List].sort(sortFunc)},
     [List,sortFunc]);


  return(
    <div> {sortedList.join(" , ")} </div>
  )


}


function App() {






  // useMemo example


  const [numbers] = useState([10,20,30]);


  const total = useMemo( () => numbers.reduce( (acc,n)=> acc+n, 0), [numbers])


  const [names] = useState(["venkata", "satya", "siva"]);


  const sortedNames = useMemo(() => [...names].sort(),[names]); //here sorted names gets executed only when there is a change in names array




  const [count1, setcount1] = useState(0);
  const[count2, setcount2] = useState(0);


  const countTotal = useMemo(()  => count1+count2, [count1,count2]); // this is a bad use of useMemo as it deals with scalers


  const sortFunc = useCallback( (a,b) => a.localeCompare(b), []); // function that compares two strings and sorts them


  // implement useCallback only when you dont want reference to be changed or when you are sending calcuated data or function on to a nested component where you dont know the implementation
  // do not implement useCallback on simple html elements for onChange or onClick
  // useCallback can be used in custom hoooks so that the created function will not break the code



  return (
    <div>
      <button onClick={() => setcount1(count1+1)}> {count1}</button>
      <button onClick={() => setcount2(count2+1)}> {count2}</button>
      <div>Total: {countTotal}</div>


      <div>Names: {names.join(" , ")}</div>


      {/* <div>Sorted Names: {sortedNames.join(" , ")}</div>   */}


      <SortedList List={names} sortFunc={sortFunc}/>

      </div>

  )
}


export default App

In the above example we can see that the console.log outside the function runs when ever the component renders but the console.log in the function that we used in the useCallback gets run only when the dependency changes, just go ahead and try it yourself the code is in my GitHub named as native-UseMemoandCallback.

useMemo vs useCallback

the main difference between useCallback and useMemo is the type of value they return. useCallback returns a memoized callback function, while useMemo returns a memoized value. Both hooks can be used to optimize the performance of your React components by avoiding unnecessary re-creations of functions or values.

The above code is available in my GitHub repository link is here

If you like the article, follow me on hashnode or bookmark my blog for more articles like this.

Did you find this article valuable?

Support Saravan Krishna's blog by becoming a sponsor. Any amount is appreciated!