Функциональные компоненты в Preact представляют собой обычные JavaScript-функции, которые возвращают разметку JSX. В отличие от классовых компонентов, они не имеют собственного состояния и методов жизненного цикла по умолчанию. Основная задача функционального компонента — принимать props и возвращать JSX.
import { h } from 'preact';
function Button({ label, onClick }) {
return <button onCl ick={onClick}>{label}</button>;
}
Ключевым моментом является то, что функциональные компоненты более
лёгкие и предсказуемые, поскольку не требуют this и не
создают экземпляров классов.
useState для состоянияХук useState позволяет хранить локальное состояние в
функциональных компонентах. Он возвращает массив из двух элементов:
текущее значение состояния и функцию для его обновления.
import { h } from 'preact';
import { useState } from 'preact/hooks';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Текущее значение: {count}</p>
<button onCl ick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}
Особенности:
useState может принимать начальное значение любого
типа: число, строку, объект, массив.setCount(prev => prev + 1)) гарантирует корректность
при асинхронных изменениях.useState создаёт отдельную независимую
ячейку состояния.useEffectХук useEffect позволяет выполнять действия после рендера
компонента: запросы к API, подписки, таймеры, модификацию DOM.
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval); // очистка при размонтировании
}, []); // пустой массив зависимостей — эффект выполнится один раз
return <p>Прошло секунд: {seconds}</p>;
}
Ключевые моменты:
useEffect — массив зависимостей. Эффект
выполняется при изменении любой из зависимостей.useEffect заменяет большинство методов жизненного цикла
классовых компонентов (componentDidMount,
componentDidUpdate,
componentWillUnmount).useRef
для доступа к DOM и сохранения значенийХук useRef создаёт объект, который сохраняет своё
значение между рендерами без триггера повторного рендера.
import { h } from 'preact';
import { useRef } from 'preact/hooks';
function FocusInput() {
const inputRef = useRef();
const focus = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} />
<button onCl ick={focus}>Сфокусировать</button>
</div>
);
}
Применение useRef:
inputRef.current).useMemo и
useCallback для оптимизацииuseMemo мемоизирует вычисленные значения, предотвращая
их повторное вычисление при каждом рендере.
import { h } from 'preact';
import { useMemo } from 'preact/hooks';
function ExpensiveCalculation({ value }) {
const result = useMemo(() => {
console.log('Вычисление...');
return value ** 2;
}, [value]);
return <p>Результат: {result}</p>;
}
useCallback мемоизирует функции, чтобы их ссылка
оставалась неизменной между рендерами.
import { h } from 'preact';
import { useState, useCallback } from 'preact/hooks';
function ButtonWrapper() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(c => c + 1);
}, []);
return <button onCl ick={increment}>Счёт: {count}</button>;
}
Рекомендации по применению:
useMemo и useCallback при
дорогих вычислениях или передаче функций в дочерние компоненты, чтобы
избежать ненужных ререндеров.Пользовательские хуки позволяют инкапсулировать повторяющуюся логику и переиспользовать её в разных компонентах.
import { useState, useEffect } from 'preact/hooks';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(json => {
setData(json);
setLoading(false);
});
}, [url]);
return { data, loading };
}
Использование:
function UsersList() {
const { data, loading } = useFetch('https://jsonplaceholder.typicode.com/users');
if (loading) return <p>Загрузка...</p>;
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}
Преимущества:
useContextКонтекст позволяет передавать данные через дерево компонентов без явного пробрасывания пропсов.
import { h, createContext } from 'preact';
import { useContext } from 'preact/hooks';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Кнопка</button>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
Особенности:
useContext возвращает текущее значение контекста.Provider автоматически вызывает
повторный рендер всех компонентов, использующих этот контекст.Комбинирование нескольких хуков позволяет полностью заменить классовые компоненты с состоянием и жизненным циклом. Типичная структура функционального компонента:
useState.useEffect.useRef.useMemo и
useCallback.useContext.Функциональные компоненты с хуками предоставляют гибкий и компактный способ построения интерфейсов в Preact, минимизируя шаблонный код и упрощая управление состоянием.