DEV Community

Cover image for React-hooks - useState, useEffect, useRef, useMemo
vinodchauhan7
vinodchauhan7

Posted on • Updated on

React-hooks - useState, useEffect, useRef, useMemo

Picture this : You have a excellent function component in your app, but one day you need to add a lifecycle method in it. After a moment you think, you can convert function component into a class & there you go.

You will convert class Temp extends React.Component, and then copy your return function in render body.However, New React-Hooks has the better way to do it. And you can use state in function components & lifeCycle methods also.

Note : Basic of React will be required for this article.

Hooks, let you plug in state & lifeCycle react features into functional component.

useState :

This hook will let you add state in functional component. In class component we can have ‘this’. With ‘this’ help we can initialize state in constructor and can do our work. But in functional component, We have no ‘this’ so we cannot assign or read from ‘this’.

import React, { useState } from 'react';

// Declare a new state variable, which we'll call "count"
   const [count, setCount] = useState(0);

In above instance, we have used ‘useState’ from react package. In this example, we have one variable ‘count’ whose value is set in useState(0) as an argument. So ‘0’ will be its initial-Value, it can be any dataType as per your requirement.

// Can be modified as setCount method which we mentioned in useState.

<button onClick={() => setCount(count + 1)}> 
    {count} // Can be read in this way
  </button>
Full Example :
   import React, { useState } from 'react';
   function Example() {
     const [count, setCount] = useState(0);
     return (<division> <h3>You clicked {count} times</h3>
      <button onClick={() => setCount(count + 1)}>
       Click me
        </button>
     <division/>
   );
  }

When we declare a state variable with useState, it returns a pair — an array with two items. The first item is the current value, and the second is a function that lets us update it.

Custom hooks :

The best thing about React hooks is that they are regular JS function calls, so we can refactor all the logic for them into little function.

// 🐨 Make a custom hook called useCounter that accepts the step and
// initialCount and returns the count and increment function function

useCounter({stepCount = 1, initialCount = 0}) {
 const [count, setCount] = React.useState(initialCount)
 const increment = () => setCount(count + stepCount)
 return [count, increment]
}
function Counter({step = 1, initialCount = 0}) {
 const [count, increment] = useCounter(step, initialCount)
 return <buton onClick={increment}>{count}</buton>
}

useEffect :

You can handle 3 lifecycle events directly inside the function components with ‘useEffect’, namely : componentDidMount, componentDidUpdate , componentWillUnmount.

Sometimes we want our code to run each & every time on rendering. The callback we’re passing to React.useEffect is called after every render of our component (including re-render).

React.useEffect( () => {
   Console.log("useEffect runs");
});

But sometimes we only want to useEffect callback function to run at the change of our variable value. In that case, Luckily for us,React.useEffect allows you to pass a second argument called the “dependency array” which signals to React that your effect callback function should be called when (and only when) those dependencies change. So we can use this to avoid doing unnecessary work!

//Custom useState hook 
function useLocalStorageCounter({step = 1, initialCount = 0, key = 'count'}) {
const [count, setCount] = React.useState(() =>
  Number(window.localStorage.getItem('count') || initialCount),
)
React.useEffect(() => {
window.localStorage.setItem('count', count)
}, [count]);

const increment = () => setCount(c => c + step)
return [count, increment]
}

If I provide empty dependency in useEffect then it means I only want to load callBack function at initial Load. Or If I return something from callBack function then it will behave like componentWillUnmount lifeCycle method.

useRef:

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

function formMethod() {
  const username= useRef(null);
  const onUsernameClick = () => {
    // `current` points to the mounted text input element
    username.current.focus();
  };
  return (
      <input> ref={username} type="text"</>
      <buton onClick={onUsernameClick}>Focus the input</buton>  
  );
}

Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render.

useMemo:

const memoizedValue = useMemo(() => modifyValue(a), [a]);

useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
Remember that the function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering.If no array is provided, a new value will be computed on every render.

To get your hands dirty in code, I have made one example Tic Tac Toe game in react hooks on CodeSandbox.
https://codesandbox.io/s/tictactoe-react-hooks-fjth8

https://github.com/vinodchauhan7/react-hooks-ticTacToe

Please provide your constructive comments and share if you like this.

Top comments (3)

Collapse
 
dance2die profile image
Sung M. Kim

Thank you for the post, @vinodchauhan7 .

May I request to update the code formatting?

Please refer to the Editor Guide 😉.

Collapse
 
vinodchauhan7 profile image
vinodchauhan7

Sure Kim

Collapse
 
dance2die profile image
Sung M. Kim

Fabulous 😎 thanks, mate