Состояние (state) является ключевым элементом в архитектуре
компонентов Preact. Оно представляет собой объект, который хранит
данные, определяющие текущее поведение и отображение компонента. В
Preact состояние обычно создается с помощью хука
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 возвращает массив из двух элементов: текущее
значение состояния и функцию для его обновления.Для сложных структур данных и более контролируемого обновления
состояния используется хук useReducer. Он
позволяет описывать логику изменения состояния через редьюсер — функцию,
которая принимает текущее состояние и действие, возвращая новое
состояние.
import { h } from 'preact';
import { useReducer } from 'preact/hooks';
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:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Счётчик: {state.count}</p>
<button onCl ick={() => dispatch({ type: 'increment' })}>Увеличить</button>
<button onCl ick={() => dispatch({ type: 'decrement' })}>Уменьшить</button>
</div>
);
}
Преимущества useReducer:
В Preact локальное состояние удобно для отдельных компонентов. Для
обмена данными между компонентами используют контекст
(createContext). Контекст позволяет передавать
данные глубоко в дерево компонентов без явного проброса через props.
import { h } from 'preact';
import { createContext } from 'preact';
import { useContext, useState } from 'preact/hooks';
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}
onCl ick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
Переключить тему
</button>
);
}
Особенности контекста:
Для управления побочными эффектами (side effects)
применяется хук useEffect, который
синхронизирует состояние с внешними действиями: запросами к API,
подписками, таймерами.
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(setData);
}, []); // пустой массив зависимостей — вызов один раз при монтировании
if (!data) return <p>Загрузка...</p>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
Принципы работы useEffect:
Перерисовка компонентов происходит при изменении состояния или props. Для повышения производительности:
useMemo для кэширования
вычислений, зависящих от состояния.useCallback для сохранения
функций, чтобы не вызывать лишние перерендеры дочерних компонентов.import { h } from 'preact';
import { useState, useMemo } from 'preact/hooks';
function ExpensiveCalculation({ num }) {
const result = useMemo(() => {
console.log('Вычисление...');
return num * 2;
}, [num]);
return <p>Результат: {result}</p>;
}
Использование этих подходов позволяет строить компоненты Preact эффективными, с управляемым состоянием и минимальной нагрузкой на рендеринг, сохраняя при этом чистоту и предсказуемость архитектуры.