DEV Community

SangeetaGogoi
SangeetaGogoi

Posted on

Lesser used React Hooks

In this blog we are going to talk about React hooks that are not used commonly.

1. useMemo Hook :

The useMemo is a hook used in the functional component of react that returns a memoized value.In react also, we use this concept, whenever in the React component, the state and props do not change the component and the component does not re-render, it shows the same output.

Syntax :

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

Enter fullscreen mode Exit fullscreen mode

useMemo takes in a function and an array of dependencies.

Usage of useMemo :

const memoizedList = useMemo(() => {
  return userList.map(user => {
    return {
      ...user,
      name: someExpensiveOperation(user.name)
    } 
  }) 
}, [userList])
Enter fullscreen mode Exit fullscreen mode

2. useCallback Hook :

The useCallback hook is used when we have a component in which the child is rerendering again and again without need.

Syntax :

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
Enter fullscreen mode Exit fullscreen mode

Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed.

Purpose of useCallback

function MyComponent() {
  // handleClick is re-created on each render
  const handleClick = () => {
    console.log('Clicked!');
  };

  // ...
}
Enter fullscreen mode Exit fullscreen mode

handleClick is a different function object on every rendering of MyComponent.

But in some cases you need to maintain a single function instance between renderings:

  1. A functional component wrapped inside React.memo() accepts a function object prop
  2. When the function object is a dependency to other hooks, e.g. useEffect(..., [callback])
  3. When the function has some internal state, e.g. when the function is debounced or throttled.

That’s when useCallback(callbackFun, deps) is helpful: given the same dependency values deps, the hook returns (aka memoizes) the function instance between renderings:

import { useCallback } from 'react';

function MyComponent() {
  // handleClick is the same function object
  const handleClick = useCallback(() => {
    console.log('Clicked!');
  }, []);

  // ...
}
Enter fullscreen mode Exit fullscreen mode

3.useReducer Hook :

useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

Syntax

const [state, dispatch] = useReducer(reducer, initialArg, init);
Enter fullscreen mode Exit fullscreen mode

It accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. (If you’re familiar with Redux, you already know how this works.

Here is the countReducer example;

const initialState = { count: 0 }

const counterReducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}
Enter fullscreen mode Exit fullscreen mode

Specifying the initial State

Two ways to initialized the useReducer state;

1. Basic :

We can just give it as a second argument to useReducer call;

const [state, dispatch] = useReducer(
  countReducer,
  { count: 0 } // second argument
);
Enter fullscreen mode Exit fullscreen mode

2. Lazy Initialization :

const initState = (defaultCount) => ({ count: defaultCount })

const Counter = ({ counter }) => {
    const [state, dispatch] = useReducer(
      countReducer,
      counter, // second argument
        initState // third argument
    );

    // Rest of the component...
}
Enter fullscreen mode Exit fullscreen mode

Usage
After we initialize it we just need to call dispatch functions that we are getting from useReducer hook and use it as a handler inside our elements.

React guarantees that dispatch function identity is stable and won’t change on re-renders.

const Counter = ({ counter }) => {
    const [state, dispatch] = useReducer(countReducer, 0);

    return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)