Props — основной способ передачи данных от родительского компонента к дочернему. В Preact props неизменяемы внутри дочернего компонента, что обеспечивает предсказуемость и стабильность состояния. Простейший пример:
import { h } from 'preact';
function Child({ message }) {
return <p>{message}</p>;
}
function Parent() {
return <Child message="Привет из родителя!" />;
}
Ключевые моменты:
function Child({ onClick }) {
return <button onCl ick={onClick}>Нажми меня</button>;
}
function Parent() {
const handleClick = () => alert('Кнопка нажата');
return <Child onCl ick={handleClick} />;
}
Компоненты Preact могут содержать локальное состояние через хук
useState. Это состояние управляет внутренними данными и не
зависит напрямую от props. Важный паттерн — поднятие состояния вверх
(lifting state up).
import { h } from 'preact';
import { useState } from 'preact/hooks';
function Counter({ value, onChange }) {
return (
<div>
<button onCl ick={() => onChange(value - 1)}>-</button>
<span>{value}</span>
<button onCl ick={() => onChange(value + 1)}>+</button>
</div>
);
}
function App() {
const [count, setCount] = useState(0);
return <Counter value={count} onCha nge={setCount} />;
}
Контекст обеспечивает передачу данных через дерево компонентов без необходимости пробрасывать props через каждый уровень. Это особенно полезно для глобальных настроек, темы или авторизации.
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';
const ThemeContext = createContext('light');
function Toolbar() {
const theme = useContext(ThemeContext);
return <div className={`toolbar ${theme}`}>Toolbar с темой {theme}</div>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
Provider позволяет динамически менять
контекст на уровне поддеревьев компонентов.useContext автоматически
обновляет компонент при изменении значения.Прямое изменение состояния родителя из дочернего компонента невозможно без передачи функций. Паттерн обратного вызова (callback) решает эту задачу.
function Child({ notify }) {
return <button onCl ick={() => notify('Данные из Child')}>Отправить</button>;
}
function Parent() {
const handleNotification = message => console.log(message);
return <Child notify={handleNotification} />;
}
Создание собственных хуков позволяет инкапсулировать логику передачи и управления данными, делая компоненты компактнее и читаемее.
import { useState } from 'preact/hooks';
function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
return { count, increment, decrement };
}
function Counter() {
const { count, increment, decrement } = useCounter(10);
return (
<div>
<button onCl ick={decrement}>-</button>
<span>{count}</span>
<button onCl ick={increment}>+</button>
</div>
);
}
В больших приложениях чаще всего используется сочетание props, state и контекста:
import { h, createContext } from 'preact';
import { useState, useContext } from 'preact/hooks';
const UserContext = createContext(null);
function Profile() {
const user = useContext(UserContext);
return <div>Пользователь: {user.name}</div>;
}
function App() {
const [user, setUser] = useState({ name: 'Алексей' });
return (
<UserContext.Provider value={user}>
<Profile />
<button onCl ick={() => setUser({ name: 'Мария' })}>Сменить пользователя</button>
</UserContext.Provider>
);
}
Эффективное управление передачей данных между компонентами Preact основывается на чёткости потока данных, минимизации ненужных обновлений и использовании подходящих инструментов для каждой задачи: props для простого потока, state для локального состояния, context для глобального доступа, callback и хуки для гибкой логики.