WebSocket — это протокол, обеспечивающий двустороннюю связь между клиентом и сервером поверх TCP. В отличие от традиционных HTTP-запросов, где клиент инициирует каждое соединение, WebSocket позволяет поддерживать постоянное соединение, что делает возможным реальное время в веб-приложениях. В Preact это особенно важно для создания динамических интерфейсов, где состояние компонентов зависит от событий на сервере.
Для установки WebSocket соединения используется встроенный объект
WebSocket:
const socket = new WebSocket('ws://localhost:8080');
socket.ono pen = () => {
console.log('Соединение открыто');
};
socket.onmess age = (event) => {
console.log('Получено сообщение:', event.data);
};
socket.oncl ose = () => {
console.log('Соединение закрыто');
};
socket.oner ror = (error) => {
console.error('Ошибка WebSocket:', error);
};
При работе с Preact важно учитывать, что WebSocket соединение должно управляться жизненным циклом компонентов, чтобы избежать утечек памяти и лишних соединений.
В Preact используются хуки useState и
useEffect, которые идеально подходят для управления
состоянием реального времени. Например, для создания чата:
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
function Chat() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
useEffect(() => {
const socket = new WebSocket('ws://localhost:8080');
socket.onmess age = (event) => {
setMessages(prev => [...prev, event.data]);
};
return () => {
socket.close();
};
}, []);
const sendMessage = () => {
if (input.trim()) {
socket.send(input);
setInput('');
}
};
return (
<div>
<ul>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
<input
type="text"
value={input}
onIn put={e => setInput(e.target.value)}
/>
<button onCl ick={sendMessage}>Отправить</button>
</div>
);
}
Ключевой момент — закрытие соединения в функции очистки
useEffect, чтобы WebSocket не оставался открытым
при размонтировании компонента.
Использование WebSocket в Preact требует особого внимания к состоянию приложения. Для сложных проектов рекомендуется применять централизованное хранилище состояния (например, через Context API), чтобы несколько компонентов могли реагировать на одни и те же события сервера:
import { createContext } from 'preact';
import { useState, useEffect, useContext } from 'preact/hooks';
const SocketContext = createContext(null);
export function SocketProvider({ children }) {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState([]);
useEffect(() => {
const ws = new WebSocket('ws://localhost:8080');
ws.onmess age = (event) => {
setMessages(prev => [...prev, event.data]);
};
setSocket(ws);
return () => ws.close();
}, []);
return (
<SocketContext.Provider value={{ socket, messages }}>
{children}
</SocketContext.Provider>
);
}
export function useSocket() {
return useContext(SocketContext);
}
Любой компонент внутри SocketProvider может получать
актуальные данные и отправлять сообщения, не создавая новых
соединений.
function createWebSocket(url, onMessage) {
let socket;
const connect = () => {
socket = new WebSocket(url);
socket.onmess age = onMessage;
socket.oncl ose = () => setTimeout(connect, 1000);
socket.oner ror = () => socket.close();
};
connect();
return {
send: (msg) => socket.readyState === WebSocket.OPEN && socket.send(msg)
};
}
Буферизация сообщений: Если соединение временно недоступно, можно сохранять сообщения в очередь и отправлять их при восстановлении соединения.
Обновление состояния компонентов: Избегать
прямого изменения состояния при каждом сообщении от сервера.
Использование requestAnimationFrame или
throttle помогает оптимизировать частоту обновлений
интерфейса.
WebSocket в Preact особенно полезен для:
Благодаря минимальной нагрузке на DOM и быстрому рендерингу, Preact позволяет создавать легкие и отзывчивые интерфейсы, полностью использующие возможности WebSocket.
useEffect для управления жизненным циклом
соединения.Такой подход обеспечивает эффективную работу real-time функций и минимизирует ошибки при масштабировании приложения.