Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Примеры использования хуков в React
Хуки — это функции, которые позволяют использовать состояние и другие возможности React без написания классов. Они были добавлены в React 16.8 и стали стандартом для работы с состоянием,副作用 (side effects) и другими возможностями в функциональных компонентах. Вот ключевые примеры с пояснениями:
1. useState — работа с состоянием
useState позволяет добавить состояние в функциональный компонент. Он возвращает массив из двух элементов: текущее значение состояния и функцию для его обновления.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Инициализация состояния
return (
<div>
<p>Вы нажали {count} раз</p>
<button onClick={() => setCount(count + 1)}>
Нажми меня
</button>
<button onClick={() => setCount(0)}>
Сбросить
</button>
</div>
);
}
2. useEffect — работа с побочными эффектами
useEffect позволяет выполнять побочные эффекты в функциональных компонентах: запросы к API, подписки, мануальные изменения DOM. Он заменяет методы жизненного цикла componentDidMount, componentDidUpdate и componentWillUnmount.
import React, { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Эта функция выполнится после каждого рендера,
// если изменится userId (указано в массиве зависимостей)
async function fetchUser() {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
}
fetchUser();
// Функция очистки (аналог componentWillUnmount)
return () => {
console.log('Компонент размонтируется или userId изменился');
};
}, [userId]); // Массив зависимостей: эффект сработает при изменении userId
if (loading) return <div>Загрузка...</div>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
3. useContext — работа с контекстом
useContext позволяет подписаться на контекст без использования Consumer. Это упрощает доступ к глобальным данным (например, теме, языку, состоянию авторизации).
import React, { useContext, createContext } from 'react';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext); // Получаем текущую тему
return (
<button style={{
background: theme === 'dark' ? '#333' : '#FFF',
color: theme === 'dark' ? '#FFF' : '#333'
}}>
Тема: {theme}
</button>
);
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
4. useReducer — альтернатива useState для сложного состояния
useReducer предпочтителен, когда следующее состояние зависит от предыдущего, или логика обновления сложная. Похож на Redux.
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 };
case 'reset':
return initialState;
default:
throw new Error('Неизвестное действие');
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Счет: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>
Увеличить
</button>
<button onClick={() => dispatch({ type: 'decrement' })}>
Уменьшить
</button>
<button onClick={() => dispatch({ type: 'reset' })}>
Сбросить
</button>
</div>
);
}
5. Кастомные хуки — повторное использование логики
Кастомные хуки позволяют инкапсулировать и переиспользовать логику между компонентами. Это функции, имя которых начинается с use, и которые могут вызывать другие хуки.
import { useState, useEffect } from 'react';
// Кастомный хук для отслеживания ширины окна
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
// Очистка при размонтировании
return () => window.removeEventListener('resize', handleResize);
}, []); // Пустой массив зависимостей = эффект только при монтировании
return width;
}
function ResponsiveComponent() {
const width = useWindowWidth(); // Используем кастомный хук
return (
<div>
<p>Ширина окна: {width}px</p>
{width < 768 ? <p>Мобильный вид</p> : <p>Десктопный вид</p>}
</div>
);
}
6. useRef — доступ к DOM и хранение мутируемых значений
useRef возвращает мутируемый ref-объект, который сохраняет свое значение между рендерами. Часто используется для доступа к DOM-элементам или хранения значений, не требующих перерисовки.
import React, { useRef, useEffect } from 'react';
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // Устанавливаем фокус на инпут при монтировании
}, []);
return <input ref={inputRef} type="text" />;
}
7. useMemo и useCallback — оптимизация производительности
- useMemo мемоизирует вычисления, чтобы избежать дорогостоящих пересчетов при каждом рендере.
- useCallback мемоизирует функции, предотвращая их пересоздание.
import React, { useState, useMemo, useCallback } from 'react';
function ExpensiveComponent({ list, multiplier }) {
// Вычисление выполняется только при изменении list или multiplier
const computedValue = useMemo(() => {
console.log('Выполняется дорогое вычисление...');
return list.reduce((sum, item) => sum + item, 0) * multiplier;
}, [list, multiplier]);
const handleClick = useCallback(() => {
console.log('Клик! Значение:', computedValue);
}, [computedValue]); // Функция не пересоздается при каждом рендере
return (
<div>
<p>Результат: {computedValue}</p>
<button onClick={handleClick}>Логгировать</button>
</div>
);
}
Заключение
Хуки кардинально изменили подход к разработке на React, сделав функциональные компоненты полноценными. Они обеспечивают:
- Улучшенную композицию логики (кастомные хуки)
- Избавление от проблем классов (this, привязка методов)
- Более понятный и тестируемый код
Главное правило: хуки можно вызывать только на верхнем уровне компонентов или других хуков, а не внутри циклов, условий или вложенных функций. Это гарантирует сохранение порядка вызовов хуков между рендерами.