Most useful React hooks

Mindaugas Nakrosis
4 min readFeb 26, 2021
Photo by Lynda Hinton on Unsplash

Hooks let you use state and other React features without writing a class. I’ll be writing about the ones I use most often.

1. useState

import React, { useState } from 'react';function Example() {
// Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

We get a tuple as a return value from useState. State value and a function to change that state. Using this hook we can have functional components with state.

2. useEffect

This hook adds the ability to perform side effects from a function component. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes, but unified into a single API.

For example, this component sets the document title after React updates the DOM:

import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);

useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

useEffect has an optional second argument. It is an array of properties on which change the useEffect callback (first argument) gets called.

useEffect(() => console.log(count), [count]);

For example this line of code will log the count value every time it changes.

If you want useEffect to get called one time on initial render, for example to load data. You can pass empty array as a second argument like this:

useEffect(() => {
fetchSomeAPI();
}, []);

If you want you to cleanup some code like on componentWillUnmount it can be achieved like this:

useEffect(() => {
fetchSomeAPI();
return () => {
cleanupHere();
};
}, []);

3. useMemo

Used to memoize a calculation result between a function's calls and between renders.

But what does that mean?

useMemo focuses on avoiding heavy calculation.

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

Pass a “create” function and an array of dependencies. useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.

Function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.

If no array is provided, a new value will be computed on every render.

4. useCallback

useCallback focuses on a different than useMemo. It fixes performance issues when inline event handlers like onClick={() => { doSomething(...); } cause PureComponent child re-rendering (because function expressions there are referentially different each time)

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

Returns a memoized callback.

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. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

5. useRef

Is used to keep data between renders (updating does not fire re-rendering).

const refContainer = useRef(initialValue);

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.

A common use case is to access a child imperatively:

function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}

Essentially, useRef is like a “box” that can hold a mutable value in its .current property.

You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with <div ref={myRef} />, React will set its .current property to the corresponding DOM node whenever that node changes.

However, useRef() is useful for more than the ref attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.

This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render.

Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.

--

--