diff --git a/lessons/lesson32/lesson.md b/lessons/lesson32/lesson.md index eb66b0d..eda819a 100644 --- a/lessons/lesson32/lesson.md +++ b/lessons/lesson32/lesson.md @@ -52,7 +52,13 @@ const handleMouseLeave = () => setIsHovered(false); -HOC +HOC (Higher-Order Components) + +- Функция, которая принимает компонент и возвращает новый компонент +- Позволяет добавлять логику "снаружи" +- Используется для переиспользования поведения + + ```jsx function withHover(WrappedComponent) { @@ -78,8 +84,27 @@ export default withHover(MyComponent); +Плюсы: + +- Разделение обязанностей (UI отдельно, логика отдельно) +- Легко оборачивать несколько компонентов + +Минусы: + +- "Wrapper hell" (дерево компонентов сильно усложняется) +- Возможны конфликты props +- Логика скрыта внутри обёртки + + + Render Props +- Компонент принимает функцию как child +- Эта функция управляет тем, что будет отрисовано +- Позволяет гибко делиться состоянием и поведением + + + ```jsx function Hover({ children }) { const [isHovered, setIsHovered] = useState(false); @@ -106,14 +131,20 @@ function App() { -Оба подхода рабочие, но имеют недостатки: +Плюсы: -- "Wrapper Hell": Дерево компонентов разрастается за счет оберток. -- Неявные зависимости: Сложно понять, откуда приходят props. -- Конфликты имен: Props от разных HOC могут перезаписывать друг друга. +- Гибкость — родитель решает, как отрисовать +- Чёткий контроль над данными + +Минусы: + +- Синтаксис иногда "шумный" +- Легко создать "пирамиду функций" +Оба подхода рабочие, но имеют недостатки + Хуки предложили более элегантное решение. @@ -218,26 +249,25 @@ function UserProfile() { Создаем хук useRequest ```jsx -Копировать код -import { useState, useEffect } from 'react'; +import { useState, useEffect } from "react"; export function useRequest(url) { - const [data, setData] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - if (!url) return; - - setIsLoading(true); - fetch(url) - .then(res => res.json()) - .then(data => setData(data)) - .catch(err => setError(err)) - .finally(() => setIsLoading(false)); - }, [url]); - - return { data, isLoading, error }; + const [data, setData] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + if (!url) return; + + setIsLoading(true); + fetch(url) + .then((res) => res.json()) + .then((data) => setData(data)) + .catch((err) => setError(err)) + .finally(() => setIsLoading(false)); + }, [url]); + + return { data, isLoading, error }; } ``` @@ -267,10 +297,9 @@ function UserProfile({ userId }) { хук useInput ```jsx -Копировать код function useInput(initial = "") { const [value, setValue] = useState(initial); - const onChange = e => setValue(e.target.value); + const onChange = (e) => setValue(e.target.value); return { value, onChange }; } ```