React.js hooks have transformed the way developers build modern web applications. Before React 16.8, managing state and side effects required class components, making the code more complex and harder to maintain. Hooks introduced a cleaner, more functional approach, allowing developers to use state and other React features without writing a class.
React.js hooks have transformed the way developers build modern web applications. Before React 16.8, managing state and side effects required class components, making the code more complex and harder to maintain. Hooks introduced a cleaner, more functional approach, allowing developers to use state and other React features without writing a class. In this article, we'll explore 10 essential React.js hooks that every modern developer should know. These hooks help manage state, optimize performance, and enhance code reusability, making them indispensable for React development.
The useState hook is one of the most fundamental hooks in React. It allows functional components to manage local state, eliminating the need for class-based state management.
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 useEffect hook allows developers to handle side effects like API calls, event listeners, and subscriptions inside functional components.
import React, { useState, useEffect } from 'react'; function DataFetcher() { const [data, setData] = useState([]); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)); }, []); // Empty dependency array means it runs only once return <div>{JSON.stringify(data)}</div>; }
The useContext hook simplifies state management by allowing components to access shared state without prop drilling.
import React, { useContext, createContext } from 'react'; const ThemeContext = createContext(); function ThemedComponent() { const theme = useContext(ThemeContext); return <div style={{ background: theme }}>Current Theme: {theme}</div>; } function App() { return ( <ThemeContext.Provider value="dark"> <ThemedComponent /> </ThemeContext.Provider> ); }
The useRef hook is commonly used for direct DOM manipulation and storing values between renders without triggering re-renders.
import React, { useRef } from 'react'; function InputFocus() { const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); }; return ( <div> <input ref={inputRef} type="text" /> <button onClick={handleClick}>Focus Input</button> </div> ); }
The useReducer hook is useful for managing complex state logic, offering a more structured approach than useState.
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: return state; } } function Counter() { const [state, dispatch] = useReducer(reducer, { count: 0 }); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </div> ); }
The useMemo hook helps optimize performance by memoizing expensive computations, preventing unnecessary recalculations during renders.
import React, { useState, useMemo } from 'react'; function ExpensiveComponent({ num }) { const calculateFactorial = (n) => { console.log('Calculating...'); return n <= 1 ? 1 : n * calculateFactorial(n - 1); }; const memoizedValue = useMemo(() => calculateFactorial(num), [num]); return <p>Factorial of {num}: {memoizedValue}</p>; } export default function App() { const [count, setCount] = useState(5); return ( <div> <ExpensiveComponent num={count} /> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
The useCallback hook prevents unnecessary function re-creations by memoizing callback functions, improving performance in components with frequent re-renders.
import React, { useState, useCallback } from 'react'; function Button({ handleClick }) { return <button onClick={handleClick}>Click Me</button>; } export default function App() { const [count, setCount] = useState(0); const memoizedHandleClick = useCallback(() => { setCount((prev) => prev + 1); }, []); return ( <div> <p>Count: {count}</p> <Button handleClick={memoizedHandleClick} /> </div> ); }
useLayoutEffect is similar to useEffect, but it runs synchronously after all DOM mutations and before the browser paints.
import React, { useState, useRef, useLayoutEffect } from 'react'; function MeasureComponent() { const divRef = useRef(null); const [height, setHeight] = useState(0); useLayoutEffect(() => { setHeight(divRef.current.getBoundingClientRect().height); }, []); return ( <div> <div ref={divRef} style={{ padding: '20px', background: 'lightblue' }}> Resize me </div> <p>Height: {height}px</p> </div> ); }
useImperativeHandle allows customization of a component’s exposed methods when using forwardRef.
import React, { useRef, useImperativeHandle, forwardRef } from 'react'; const CustomInput = forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }, })); return <input ref={inputRef} type="text" />; }); export default function App() { const inputRef = useRef(); return ( <div> <CustomInput ref={inputRef} /> <button onClick={() => inputRef.current.focus()}>Focus Input</button> </div> ); }
Custom hooks allow developers to extract and reuse logic across multiple components, promoting cleaner and more maintainable code.
import { useState, useEffect } from 'react'; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(url) .then((res) => res.json()) .then((data) => { setData(data); setLoading(false); }) .catch((err) => { setError(err); setLoading(false); }); }, [url]); return { data, loading, error }; } export default useFetch;
import React from 'react'; import useFetch from './useFetch'; function UsersList() { const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/users'); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <ul> {data.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ); } export default UsersList;
React hooks have drastically simplified the way developers build modern applications. From basic state management with useState to performance optimization with useMemo and useCallback, hooks offer powerful tools to make React development more efficient. Mastering these 10 essential hooks will help you write cleaner, more maintainable, and optimized React applications. Experiment with them, and start integrating them into your projects for better performance and reusability.