Preact предоставляет тонкий слой над нативным DOM, поэтому взаимодействие с ним практически не отличается от работы без фреймворка. В отличие от более тяжёлых решений, Preact не абстрагирует DOM полностью и не скрывает Web APIs.
refДля прямого взаимодействия с DOM-узлами используется механизм
ref, который передаёт ссылку на реальный элемент
браузера:
import { useRef, useEffect } from 'preact/hooks';
function Example() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} />;
}
ref.current содержит HTMLInputElement, что
позволяет вызывать любые методы Web API: focus,
scrollIntoView, getBoundingClientRect.
EventСистема событий в Preact почти полностью совпадает с DOM Events.
Обработчики получают стандартный объект Event, а не
синтетическую обёртку:
function Clicker() {
function handleClick(event) {
console.log(event instanceof MouseEvent); // true
}
return <button onCl ick={handleClick}>OK</button>;
}
Это упрощает интеграцию с низкоуровневыми API браузера и сторонними библиотеками.
Preact не содержит встроенных инструментов для HTTP-запросов.
Используется стандартный fetch, доступный в браузере.
import { useEffect, useState } from 'preact/hooks';
function DataLoader() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/items')
.then(res => res.json())
.then(setData);
}, []);
if (!data) return <span>Загрузка...</span>;
return <ul>{data.map(i => <li>{i.name}</li>)}</ul>;
}
fetch возвращает Promise, а его поведение
полностью соответствует спецификации WHATWG.
Для отмены запросов применяется AbortController,
особенно полезный при размонтировании компонента:
useEffect(() => {
const controller = new AbortController();
fetch('/api/items', { signal: controller.signal });
return () => controller.abort();
}, []);
Хранилища браузера часто используются для кэширования данных и сохранения состояния.
function saveToken(token) {
localStorage.setItem('auth_token', token);
}
function loadToken() {
return localStorage.getItem('auth_token');
}
Работа с localStorage синхронная, поэтому доступ
осуществляется напрямую, без дополнительных хуков.
const [theme, setTheme] = useState(
() => localStorage.getItem('theme') || 'light'
);
useEffect(() => {
localStorage.setItem('theme', theme);
}, [theme]);
Использование ленивой инициализации состояния предотвращает лишние обращения к API.
При разработке SPA часто требуется ручное управление историей браузера.
pushState и
popstatefunction navigate(path) {
history.pushState({}, '', path);
window.dispatchEvent(new Event('popstate'));
}
В сочетании с прослушиванием события popstate
реализуется собственный роутинг без сторонних библиотек.
useEffect(() => {
const handler = () => setPath(location.pathname);
window.addEventListener('popstate', handler);
return () => window.removeEventListener('popstate', handler);
}, []);
API наблюдения за видимостью элементов полезно для ленивой загрузки и анимаций.
useEffect(() => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Элемент виден');
}
});
});
observer.observe(ref.current);
return () => observer.disconnect();
}, []);
IntersectionObserver работает асинхронно и не блокирует
основной поток.
Позволяет отслеживать изменение размеров элементов без опроса
(polling).
useEffect(() => {
const ro = new ResizeObserver(entries => {
for (const entry of entries) {
console.log(entry.contentRect.width);
}
});
ro.observe(ref.current);
return () => ro.disconnect();
}, []);
Используется для адаптивных компонентов, графиков и сложных макетов.
Preact не ограничивает использование многопоточности браузера.
const worker = new Worker('/worker.js');
worker.postMessage({ data: 42 });
worker.onmess age = e => {
console.log(e.data);
};
Обработка сообщений может обновлять состояние компонентов без блокировки UI.
Для высокопроизводительных анимаций применяется
requestAnimationFrame.
useEffect(() => {
let frameId;
function animate() {
setX(x => x + 1);
frameId = requestAnimationFrame(animate);
}
frameId = requestAnimationFrame(animate);
return () => cancelAnimationFrame(frameId);
}, []);
Взаимодействие с этим API напрямую позволяет избегать лишних абстракций и контролировать частоту обновлений.
matchMediaconst media = window.matchMedia('(prefers-color-scheme: dark)');
media.addEventListener('change', e => {
console.log(e.matches ? 'dark' : 'light');
});
Используется для реакции на системные настройки пользователя.
const audio = new Audio('/sound.mp3');
audio.play();
Все мультимедийные возможности браузера доступны без дополнительных адаптеров.
Preact хорошо сочетается с Web Components.
customElements.define('my-widget', class extends HTMLElement {
connectedCallback() {
this.textContent = 'Hello';
}
});
Использование:
<my-widget />
Preact корректно рендерит кастомные элементы и передаёт им атрибуты.
Preact не заменяет Web APIs, а органично сосуществует с ними. Компоненты выступают в роли удобной структуры, внутри которой используются нативные возможности браузера без ограничений, прокси-объектов и искусственных слоёв абстракции. Такой подход упрощает отладку, уменьшает размер бандла и сохраняет предсказуемость поведения приложения.