React Hooks
React Hooks revolutionized the way developers build React applications by allowing functional components to manage state and side effects. This guide explores advanced hooks and their practical applications.
Understanding Hooks
Hooks enable function components to use React features without writing a class. Advanced hooks help in optimizing performance, managing complex state logic, and handling side effects efficiently.
1. useReducer: Managing Complex State
useReducer
is an alternative to useState
for managing complex state logic.
Example:
import { useReducer } from 'react'; const initialState = { count: 0 }; 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, initialState); return ( <div> <p>Count: {state.count}</p> <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </div> ); } export default Counter;
2. useContext: Managing Global State
useContext
allows sharing state between components without prop drilling.
Example:
import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } function ThemedComponent() { const { theme, setTheme } = useContext(ThemeContext); return ( <div> <p>Current Theme: {theme}</p> <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle Theme </button> </div> ); }
3. useMemo: Performance Optimization
useMemo
memoizes expensive calculations.
Example:
import { useMemo, useState } from 'react'; function ExpensiveCalculation({ num }) { const squared = useMemo(() => { console.log('Calculating Square'); return num * num; }, [num]); return <p>Squared Value: {squared}</p>; }
4. useCallback: Optimizing Function References
useCallback
memoizes function instances.
Example:
import { useCallback, useState } from 'react'; function Button({ onClick }) { return <button onClick={onClick}>Click Me</button>; } function ParentComponent() { const [count, setCount] = useState(0); const increment = useCallback(() => setCount(count + 1), [count]); return ( <div> <p>Count: {count}</p> <Button onClick={increment} /> </div> ); }
5. useRef: Handling DOM and Persistent Values
useRef
stores values without causing re-renders.
Example:
import { useRef } from 'react'; function InputFocus() { const inputRef = useRef(null); return ( <div> <input ref={inputRef} type="text" /> <button onClick={() => inputRef.current.focus()}>Focus Input</button> </div> ); }
6. useLayoutEffect: Synchronous Effects
useLayoutEffect
runs synchronously after DOM mutations.
Example:
import { useLayoutEffect, useRef } from 'react'; function LayoutEffectComponent() { const divRef = useRef(null); useLayoutEffect(() => { console.log(divRef.current.offsetWidth); }); return <div ref={divRef}>Hello</div>; }