Совместное использование нескольких хуков: Как эффективно управлять логикой в React
Зачем объединять хуки?
React-хуки предоставляют мощный инструмент для работы с состоянием и эффектами в функциональных компонентах. Часто компоненты требуют выполнения нескольких задач одновременно, таких как управление состоянием, работа с API, или подписка на события.
Первый вариант: представьте компонент, который отслеживает размер окна браузера и сохраняет его в состоянии. Использование только одного хука, например useEffect, для всех задач может быстро привести к громоздкому коду. Объединяя хуки, вы можете отделить логику, связанную с событиями, от логики, связанной с состоянием.
Второй вариант: если компонент работает с несколькими источниками данных, например, с локальным состоянием и API, объединение useState и useEffect позволяет обрабатывать каждую задачу отдельно, что упрощает отладку и тестирование.
Объединение хуков помогает структурировать компонент таким образом, чтобы каждая его часть отвечала за конкретную задачу, делая код проще для чтения и поддержки.
Как эффективно комбинировать хуки?
При совместном использовании хуков важно помнить, что каждый из них выполняет свою уникальную роль. Начнем с простых рекомендаций:
Первый пример: представьте компонент, который должен показывать статус загрузки данных из API. Вы можете использовать useState для хранения состояния загрузки и данных, а useEffect для выполнения API-запроса. Вот как это может выглядеть:
import React, { useState, useEffect } from "react";
function DataLoader() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchData() {
setLoading(true);
const response = await fetch("https://api.example.com/data");
const result = await response.json();
setData(result);
setLoading(false);
}
fetchData();
}, []);
return (
<div>
{loading ? <p>Loading...</p> : <p>Data: {JSON.stringify(data)}</p>}
</div>
);
}
Второй пример: если вы хотите добавить отслеживание активности пользователя, например, определять, открыт ли пользовательскую страницу, можно добавить еще один хук useEffect, который будет подписываться на события активности. Это позволит разделить логику загрузки данных и отслеживания активности, не создавая путаницы в коде.
useEffect(() => {
function handleVisibilityChange() {
console.log(document.hidden ? "User is inactive" : "User is active");
}
document.addEventListener("visibilitychange", handleVisibilityChange);
return () => {
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, []);
Каждая задача обрабатывается своим хуком, что упрощает масштабирование компонента.
Примеры практического применения
Теперь давайте рассмотрим более сложные сценарии, когда вы работаете с несколькими хуками одновременно, и разберем, как это сделать правильно.
Первый пример: предположим, что вы создаете компонент чата. Для хранения сообщений можно использовать useState, а для подписки на новые сообщения — useEffect.
function ChatComponent() {
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState("");
useEffect(() => {
const eventSource = new EventSource("https://chat.example.com/stream");
eventSource.onmessage = (event) => {
setMessages((prev) => [...prev, event.data]);
};
return () => {
eventSource.close();
};
}, []);
const sendMessage = () => {
// Отправка сообщения через API
fetch("https://chat.example.com/send", {
method: "POST",
body: JSON.stringify({ text: newMessage }),
});
setNewMessage("");
};
return (
<div>
<ul>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
<input
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
/>
<button onClick={sendMessage}>Send</button>
</div>
);
}
Здесь useState отвечает за управление локальным состоянием сообщений, а useEffect обрабатывает подписку на события.
Второй пример: если нужно дополнительно отслеживать активность пользователя в чате, можно добавить еще один useEffect, который логирует действия пользователя.
useEffect(() => {
function logActivity() {
console.log("User is active in the chat");
}
window.addEventListener("mousemove", logActivity);
return () => {
window.removeEventListener("mousemove", logActivity);
};
}, []);
Теперь у вас есть отдельно работающие хуки для каждого аспекта функциональности.
Третий пример: вы можете комбинировать хуки для создания кастомных хуков. Например, создадим хук useWindowSize, который будет отслеживать размер окна, и подключим его к компоненту:
function useWindowSize() {
const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });
useEffect(() => {
function handleResize() {
setSize({ width: window.innerWidth, height: window.innerHeight });
}
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
return size;
}
function ResponsiveComponent() {
const { width, height } = useWindowSize();
return (
<div>
<p>Window width: {width}</p>
<p>Window height: {height}</p>
</div>
);
}
Использование кастомных хуков позволяет переиспользовать логику в других компонентах и сохранять код чистым.
Совместное использование нескольких хуков — это мощный инструмент для написания чистого и масштабируемого кода в React. Разделяйте логику на отдельные хуки, чтобы каждый из них отвечал за свою задачу. Это не только упрощает разработку, но и делает ваш код более понятным для других разработчиков. Экспериментируйте с кастомными хуками и комбинируйте их, чтобы максимально раскрыть потенциал React!






Комментарии