实时 React Hooks:SSE, WebSocket & SWR 模式 - Openclaw Skills

作者:互联网

2026-03-30

AI教程

什么是 实时 React Hooks?

实时 React Hooks 为 React 应用集成实时数据提供了一套稳健的模式。通过利用 Openclaw Skills 的这一资源,开发者可以实现具有专业级重连逻辑和错误处理的服务器发送事件 (SSE) 和 WebSockets。

该技能专注于性能和可靠性,确保 UI 状态与后端数据源保持同步,无需手动刷新页面。它处理了连接生命周期、状态管理和乐观 UI 更新的复杂性,让开发者能够专注于构建功能而非基础设施。

下载入口:https://github.com/openclaw/skills/tree/main/skills/wpank/realtime-react-hooks

安装与下载

1. ClawHub CLI

从源直接安装技能的最快方式。

npx clawhub@latest install realtime-react-hooks

2. 手动安装

将技能文件夹复制到以下位置之一

全局模式 ~/.openclaw/skills/ 工作区 /skills/

优先级:工作区 > 本地 > 内置

3. 提示词安装

将此提示词复制到 OpenClaw 即可自动安装。

请帮我使用 Clawhub 安装 realtime-react-hooks。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。

实时 React Hooks 应用场景

  • 构建具有实时性能指标的动态仪表盘。
  • 实现聊天界面和即时通知系统。
  • 创建具有流式价格更新的金融应用。
  • 开发 UI 必须即时反映多用户更改的协作工具。
实时 React Hooks 工作原理
  1. 使用目标端点 URL 初始化所需的 Hook(SSE 或 WebSocket)。
  2. Hook 建立持久连接并管理生命周期,包括组件卸载时的自动清理。
  3. 传入数据会被自动解析并存储在 React 状态或 SWR 缓存中。
  4. 如果连接丢失,重连逻辑将呈指数级触发,确保稳定性。
  5. UI 对状态变化做出反应,可选择使用乐观更新来提供无延迟体验。

实时 React Hooks 配置指南

要将此技能添加到您的项目中,请使用 Openclaw Skills CLI:

npx clawhub@latest install realtime-react-hooks

实时 React Hooks 数据架构与分类体系

特性 描述 管理的关键数据
useSSE 服务器发送事件 Hook data, isConnected, close
useWebSocket 全双工 WS Hook isConnected, send, retriesRef
useRealtimeData SWR + SSE 集成 data, mutate, isValidating
useSubscription 基于频道的编程 channels, onEvent, isConnected
name: realtime-react-hooks
model: standard
description: React hooks for real-time data with SSE, WebSocket, and SWR integration. Covers connection management, reconnection logic, and optimistic updates. Use when building React apps with real-time features. Triggers on SSE hook, WebSocket hook, real-time React, useEventSource, live updates.

Real-Time React Hooks

Production patterns for real-time data in React applications using SSE, WebSocket, and SWR.

Installation

OpenClaw / Moltbot / Clawbot

npx clawhub@latest install realtime-react-hooks

When to Use

  • React apps needing live data updates
  • Dashboards with real-time metrics
  • Chat interfaces, notifications
  • Any UI that should update without refresh

Pattern 1: SSE Hook

import { useEffect, useRef, useState, useCallback } from 'react';

interface UseSSEOptions {
  url: string;
  onMessage?: (data: T) => void;
  onError?: (error: Event) => void;
  enabled?: boolean;
}

export function useSSE({
  url,
  onMessage,
  onError,
  enabled = true,
}: UseSSEOptions) {
  const [data, setData] = useState(null);
  const [isConnected, setIsConnected] = useState(false);
  const eventSourceRef = useRef(null);

  useEffect(() => {
    if (!enabled) return;

    const eventSource = new EventSource(url);
    eventSourceRef.current = eventSource;

    eventSource.onopen = () => {
      setIsConnected(true);
    };

    eventSource.onmessage = (event) => {
      try {
        const parsed = JSON.parse(event.data) as T;
        setData(parsed);
        onMessage?.(parsed);
      } catch (e) {
        console.error('SSE parse error:', e);
      }
    };

    eventSource.onerror = (error) => {
      setIsConnected(false);
      onError?.(error);
    };

    return () => {
      eventSource.close();
      eventSourceRef.current = null;
    };
  }, [url, enabled]);

  const close = useCallback(() => {
    eventSourceRef.current?.close();
    setIsConnected(false);
  }, []);

  return { data, isConnected, close };
}

Pattern 2: WebSocket Hook with Reconnection

interface UseWebSocketOptions {
  url: string;
  onMessage?: (data: unknown) => void;
  reconnect?: boolean;
  maxRetries?: number;
}

export function useWebSocket({
  url,
  onMessage,
  reconnect = true,
  maxRetries = 5,
}: UseWebSocketOptions) {
  const [isConnected, setIsConnected] = useState(false);
  const wsRef = useRef(null);
  const retriesRef = useRef(0);

  const connect = useCallback(() => {
    const ws = new WebSocket(url);
    wsRef.current = ws;

    ws.onopen = () => {
      setIsConnected(true);
      retriesRef.current = 0;
    };

    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        onMessage?.(data);
      } catch {
        onMessage?.(event.data);
      }
    };

    ws.onclose = () => {
      setIsConnected(false);
      if (reconnect && retriesRef.current < maxRetries) {
        retriesRef.current++;
        const delay = Math.min(1000 * 2 ** retriesRef.current, 30000);
        setTimeout(connect, delay);
      }
    };

    ws.onerror = () => {
      ws.close();
    };
  }, [url, onMessage, reconnect, maxRetries]);

  useEffect(() => {
    connect();
    return () => wsRef.current?.close();
  }, [connect]);

  const send = useCallback((data: unknown) => {
    if (wsRef.current?.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify(data));
    }
  }, []);

  return { isConnected, send };
}

Pattern 3: SWR with Real-Time Updates

import useSWR from 'swr';
import { useEffect } from 'react';

export function useRealtimeData(
  key: string,
  fetcher: () => Promise
) {
  const { data, mutate, ...rest } = useSWR(key, fetcher);

  // Subscribe to real-time updates
  useEffect(() => {
    const eventSource = new EventSource(`/api/events/${key}`);

    eventSource.onmessage = (event) => {
      const update = JSON.parse(event.data);
      
      // Optimistically update cache
      mutate((current) => {
        if (!current) return update;
        return { ...current, ...update };
      }, false); // false = don't revalidate
    };

    return () => eventSource.close();
  }, [key, mutate]);

  return { data, mutate, ...rest };
}

Pattern 4: Subscription Hook

interface UseSubscriptionOptions {
  channels: string[];
  onEvent: (channel: string, data: unknown) => void;
}

export function useSubscription({ channels, onEvent }: UseSubscriptionOptions) {
  const { send, isConnected } = useWebSocket({
    url: '/api/ws',
    onMessage: (msg: any) => {
      if (msg.type === 'event') {
        onEvent(msg.channel, msg.data);
      }
    },
  });

  useEffect(() => {
    if (!isConnected) return;

    // Subscribe to channels
    channels.forEach((channel) => {
      send({ type: 'subscribe', channel });
    });

    return () => {
      channels.forEach((channel) => {
        send({ type: 'unsubscribe', channel });
      });
    };
  }, [channels, isConnected, send]);

  return { isConnected };
}

Pattern 5: Connection Status Indicator

export function ConnectionStatus({ isConnected }: { isConnected: boolean }) {
  return (
    
{isConnected ? 'Live' : 'Disconnected'}
); }

  • Meta-skill: ai/skills/meta/realtime-dashboard/ — Complete realtime dashboard guide
  • resilient-connections — Retry logic
  • design-systems/animated-financial-display — Number animations

NEVER Do

  • NEVER forget cleanup — Always close connections on unmount
  • NEVER reconnect infinitely — Use max retries with exponential backoff
  • NEVER parse without try/catch — Server might send malformed data
  • NEVER mutate and revalidate — Use mutate(data, false) for optimistic updates
  • NEVER ignore connection state — Show users when they're disconnected

Quick Reference

// SSE
const { data, isConnected } = useSSE({ url: '/api/events' });

// WebSocket
const { isConnected, send } = useWebSocket({
  url: 'wss://api.example.com/ws',
  onMessage: (data) => console.log(data),
});

// SWR + Real-time
const { data } = useRealtimeData('metrics', fetchMetrics);

// Subscriptions
useSubscription({
  channels: ['user:123', 'global'],
  onEvent: (channel, data) => updateState(channel, data),
});