In this article, we will focus on five React Hooks: useCallback
, useRef
, useMemo
, useReducer
, and useContext
. These hooks further enhance the functional components in React by allowing us to handle more complex state and side-effect management without needing class components.
useCallback
returns a memoized version of the callback function that only changes if one of the dependencies has changed. It is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(count + 1);
}, [count]);
return <button onClick={increment}>Increment</button>;
}
useRef returns a mutable ref object whose .current property is initialized to the passed argument. The returned object persists for the full lifetime of the component.
import React, { useRef } from 'react';
function TextInput() {
const inputRef = useRef();
function focusInput() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</>
);
}
useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
import React, { useMemo } from 'react';
function ExpensiveComputationComponent({ compute, value }) {
const computedValue = useMemo(() => compute(value), [compute, value]);
return <div>{computedValue}</div>;
}
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.
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
</div>
);
}
useContext accepts a context object and returns the current context value for that context. It lets you subscribe to React context within a function component.
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button theme={theme}>I'm styled by theme context!</button>;
}
In conclusion, these React Hooks (useCallback, useRef, useMemo, useReducer, and useContext) allow us to handle complex logic inside our function components, avoiding the need for class components and making our code cleaner and easier to understand. Understanding these hooks is essential for mastering modern React development.