React Hooks Cheatsheet
React Hooks revolutionized how developers write React applications by bringing the features of class components, such as state and lifecycle methods, into functional components. Hooks enable cleaner, more efficient code and help you manage state, side effects, and reusable logic. This cheatsheet explains the most commonly used hooks with examples to help you get the most out of React.
1. useState
- Manage State
The useState
hook allows you to manage state in functional components. It lets you define state variables and provides a function to update them, triggering a re-render when the state changes.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
The useState
hook takes an initial state value as an argument and returns an array with the current state and a function to update it. Whenever the state is updated, React re-renders the component.
2. useEffect
- Handle Side Effects
The useEffect
hook allows you to perform side effects in your components, such as fetching data, subscribing to external services, or updating the DOM. It runs after the component renders, and you can control when it runs by specifying dependencies.
import React, { useState, useEffect } from 'react';
function DocumentTitleUpdater() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useEffect
runs after every render by default, but by passing a dependency array (in this case, [count]
), you can control when it should run. If the dependency value hasn’t changed, React will skip the effect, which improves performance.
3. useContext
- Access Context
The useContext
hook provides a way to share values across your application without the need for prop drilling. It allows you to consume a context directly, avoiding the need to pass props down through every level of the component tree.
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ backgroundColor: theme === 'light' ? '#fff' : '#333' }}>Click Me</button>;
}
useContext
is useful when you need to pass down data to many components, such as user settings or themes, without passing it manually through props at every level.
4. useReducer
- Manage Complex State Logic
The useReducer
hook is an alternative to useState
and is particularly useful when managing complex state logic that involves multiple values or actions. It works similarly to Redux by using a reducer function to update the state.
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
useReducer
is especially helpful when the state depends on previous states or when state logic becomes complex. It provides a cleaner and more predictable way to manage updates compared to multiple useState
calls.
5. useRef
- Persistent Value and DOM Access
The useRef
hook is used to persist values between renders or to reference DOM elements directly. Unlike useState
, updates to a useRef
value do not trigger a re-render.
import React, { useRef } from 'react';
function InputFocus() {
const inputRef = useRef();
return (
<div>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus Input</button>
</div>
);
}
useRef
is commonly used for accessing DOM elements (like focusing an input field) or persisting a value across renders without causing re-renders.
6. useMemo
- Optimize Expensive Computations
The useMemo
hook memoizes the result of an expensive calculation, ensuring that the computation is only re-executed when its dependencies change. This can help optimize performance, especially for large data sets or complex calculations.
import React, { useMemo } from 'react';
function ExpensiveComputation({ numbers }) {
const sum = useMemo(() => numbers.reduce((a, b) => a + b, 0), [numbers]);
return <p>Sum: {sum}</p>;
}
useMemo
helps you avoid unnecessary recalculations by caching the result of a function, only recalculating it when necessary (when the dependencies change).
7. useCallback
- Memoize Functions
The useCallback
hook memoizes a function, preventing it from being recreated on every render. This is useful when passing functions as props to child components, as it can prevent unnecessary re-renders of those components.
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => setCount((prev) => prev + 1), []);
return (
<div>
<p>Count: {count}</p>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
return <button onClick={onClick}>Increment</button>;
}
useCallback
ensures that a function is only recreated if its dependencies change. This can improve performance when passing functions to child components.
8. useLayoutEffect
- Synchronize Layout
The useLayoutEffect
hook runs synchronously after the DOM has been updated but before the browser paints. It’s used for operations that require DOM layout measurements or adjustments before the user sees the updated UI.
import React, { useLayoutEffect, useRef } from 'react';
function LayoutEffectExample() {
const boxRef = useRef();
useLayoutEffect(() => {
console.log('Box width:', boxRef.current.offsetWidth);
});
return <div ref={boxRef}>I am a box.</div>
}
Use useLayoutEffect
when you need to measure or manipulate the DOM before the browser paints the updates to the screen, such as adjusting the layout of a component.
9. Custom Hooks - Reusable Logic
Custom hooks allow you to extract reusable logic from components and share it across multiple components. This promotes modularity and helps keep components focused on rendering.
import React, { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setData(data));
}, [url]);
return data;
}
function DataDisplay({ url }) {
const data = useFetch(url);
return <p>Data: {JSON.stringify(data)}</p>;
}
Custom hooks are great for abstracting away complex logic like data fetching, form validation, or state management, making your components easier to read and reuse.
Conclusion
React Hooks provide a powerful and flexible way to manage state, side effects, and reusable logic in functional components. By leveraging hooks like useState
, useEffect
, and useReducer
, developers can build more modular, readable, and efficient React applications. Use this cheatsheet as a reference to get familiar with these essential hooks and optimize your React code.
Follow Us:
Stay updated with our latest tips and tutorials by subscribing to our YouTube Channel.