A Deep Dive into React Hooks
React

A Deep Dive into React Hooks

July 10, 2024

React Hooks, introduced in React 16.8, allow developers to use state and other important React features in functional components—without the need for writing class-based components. Hooks help you reuse stateful logic and keep your components more readable and concise. This article explores some of the most commonly used hooks along with examples.

useState

The useState hook lets you add local state to function components. It returns an array with two elements: the current state value and a function that allows you to update it. You can use array destructuring to capture them.

const [count, setCount] = useState(0);

In the example above, count is the state variable, and setCount is the function that updates it. Calling setCount(5) would change the value of count to 5 and trigger a re-render.

State updates in React are asynchronous. If you need to update state based on the previous value, use a callback form like setCount(prev => prev + 1).

You can have multiple useState calls in one component to manage different pieces of local state independently.

useEffect

The useEffect hook lets you perform side effects in function components, such as fetching data, setting up subscriptions, or manually changing the DOM. It replaces lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount.


useEffect(() => {
  document.title = 'You clicked ' + count + ' times';
}, [count]);

You can use multiple useEffect calls within the same component, each handling different concerns, like API calls, event listeners, or cleanup logic.

To avoid memory leaks, always clean up subscriptions or event listeners inside the return function of the useEffect block.

useContext

The useContext hook lets you access the current value of a React context directly. This is useful for passing down data without prop drilling.


const theme = useContext(ThemeContext);

Context is commonly used for global settings like themes, user authentication, or language preferences.

useRef

The useRef hook returns a mutable object whose .current property is initialized to the passed argument. This object will persist for the full lifetime of the component.


const inputRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
}, []);

useRef is also useful for storing mutable values that do not cause re-renders when changed, such as timers or previous state values.

useMemo

The useMemo hook lets you memoize expensive calculations so that they are only re-computed when necessary. This can improve performance in components with costly rendering logic.


const expensiveValue = useMemo(function() {
  return computeExpensiveValue(input);
}, [input]);

Avoid overusing useMemo—only use it for performance optimization when necessary, as it adds complexity.

useCallback

The useCallback hook returns a memoized version of a callback function. It's especially useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.


const handleClick = useCallback(function() {
  console.log('Clicked!');
}, []);

useCallback is helpful in preventing re-creations of inline functions on every render, particularly in large component trees or custom hooks.

These are just a few of the built-in hooks provided by React. There are many others like useReducer, useLayoutEffect, useImperativeHandle, and the ability to create custom hooks that encapsulate shared logic across components.