Introduction
React hooks revolutionized the way developers write React components. Introduced in React 16.8, hooks allow functional components to use state and other React features without writing a class. This guide will walk you through the core concepts of React hooks, provide detailed examples, and offer practical insights for their effective use.
The Big Picture
Imagine you're constructing a building. Traditional React components are like pre-fabricated rooms – they come with everything built-in, but they're rigid and hard to customize. React hooks are like modular building blocks – they allow you to add exactly the features you need, precisely where you need them, making your code more flexible and easier to maintain.
Core Hooks
1. useState: Managing State
The useState
hook allows functional components to manage state.
Example:
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>
);
}
Key Points:
useState
returns an array with two elements: the current state value and a function to update it.- The argument to
useState
is the initial state value.
2. useEffect: Handling Side Effects
useEffect
allows you to perform side effects in functional components, such as data fetching, subscriptions, or manually changing the DOM.
Example:
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(result => setData(result));
}, []); // Empty dependency array means this effect runs once on mount
return (
<div>
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : 'Loading...'}
</div>
);
}
Key Points:
- The effect runs after every render by default.
- The second argument (dependency array) controls when the effect runs.
- Return a function from
useEffect
for cleanup operations.
3. useContext: Consuming Context
useContext
provides a way to pass data through the component tree without manually passing props.
Example:
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme }}>I'm styled by theme context!</button>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
Key Points:
useContext
accepts a context object and returns the current context value.- The component re-renders when the context value changes.
4. useReducer: Complex State Logic
useReducer
is preferable to useState
when you have complex state logic involving multiple sub-values or when the next state depends on the previous one.
Example:
import React, { 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>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
Key Points:
useReducer
returns the current state and a dispatch function.- It's useful for managing state objects with multiple sub-fields.
Advanced Hooks
5. useRef: Accessing DOM Elements
useRef
returns a mutable ref object whose .current
property is initialized to the passed argument. It's commonly used to access DOM elements directly.
Example:
import React, { useRef, useEffect } from 'react';
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
}
Key Points:
useRef
doesn't cause re-renders when its content changes.- It's useful for storing any mutable value, not just DOM refs.
6. useMemo and useCallback: Performance Optimization
These hooks help in optimizing performance by memoizing expensive computations and callback functions.
Example:
import React, { useMemo, useCallback, useState } from 'react';
function ExpensiveComponent({ data, onItemClick }) {
const sortedData = useMemo(() => {
return data.sort((a, b) => a.value - b.value);
}, [data]);
const handleClick = useCallback((item) => {
console.log('Item clicked:', item);
onItemClick(item);
}, [onItemClick]);
return (
<ul>
{sortedData.map(item => (
<li key={item.id} onClick={() => handleClick(item)}>{item.value}</li>
))}
</ul>
);
}
Key Points:
useMemo
memoizes the result of a computation.useCallback
memoizes a callback function.- Both help prevent unnecessary re-renders in child components.
Best Practices and Tips
- Don't overuse hooks: Start with simpler solutions and use hooks when you need them.
- Follow the Rules of Hooks: Only call hooks at the top level and from React functions.
- Custom Hooks: Extract reusable logic into custom hooks for better code organization.
- Dependency Arrays: Be careful with dependency arrays in
useEffect
,useMemo
, anduseCallback
. - Performance: Use the React DevTools Profiler to identify and solve performance issues.
Conclusion
React hooks provide a powerful and flexible way to use state and other React features in functional components. By mastering hooks, you can write more concise, reusable, and easier-to-understand React code. As you continue to work with hooks, you'll discover even more ways to leverage their power in your React applications.
Remember, the key to becoming proficient with hooks is practice. Start incorporating them into your projects, and you'll soon see the benefits they bring to your React development workflow.
Further Resources
Happy coding with React hooks!
'400===Dev Library > React' 카테고리의 다른 글
React 실전 프로젝트 적용기: Todo 앱 만들기 📝 (0) | 2024.10.30 |
---|---|
React 개발자를 위한 핵심 개념 총정리 🎯 (1) | 2024.10.30 |
How does the virtual DOM improve performance? (0) | 2024.06.12 |
Create a simple React component that displays a message passed as a prop. (0) | 2024.06.12 |
React Component Lifecycle Explained (1) | 2024.06.10 |