✨ From vibe coding to vibe deployment. UBOS MCP turns ideas into infra with one message.

Learn more
Carlos
  • Updated: March 20, 2026
  • 7 min read

Integrating OpenClaw Rating API Edge WebSocket Streams into a React Application

Integrating the OpenClaw Rating API Edge WebSocket streams into a React application means establishing a persistent WebSocket connection, parsing real‑time rating messages, and updating the UI instantly so users always see the latest scores.

1. Introduction

Real‑time data is the new competitive edge for front‑end developers. Whether you are building a live leaderboard, a product review widget, or a streaming analytics dashboard, the OpenClaw Rating API provides low‑latency rating updates via Edge WebSocket streams. This guide walks you through the entire integration process—from installing dependencies to rendering live ratings in a performant React UI.

While the focus is on OpenClaw, the patterns described here apply to any WebSocket‑based service. You’ll also discover how the UBOS homepage can host your React app with zero‑config deployment, and why the UBOS platform overview is a solid foundation for scaling real‑time workloads.

2. Prerequisites

  • Node.js ≥ 14 and npm ≥ 6
  • React ≥ 18 (Create React App, Vite, or Next.js)
  • Basic knowledge of WebSocket protocol
  • An active OpenClaw API key (obtainable from the OpenClaw dashboard)

If you’re new to React, the Web app editor on UBOS offers a visual starter that can bootstrap a project in seconds.

3. Setting Up the WebSocket Connection

3.1 Installing dependencies

The only required library is reconnecting-websocket, which automatically handles reconnection logic.

npm install reconnecting-websocket

3.2 Creating a reusable WebSocket hook

A custom hook keeps the connection logic isolated and reusable across components. Below is a TypeScript‑friendly implementation:

import { useEffect, useRef, useState } from 'react';
import ReconnectingWebSocket from 'reconnecting-websocket';

interface RatingMessage {
  productId: string;
  rating: number;
  timestamp: string;
}

/**
 * useOpenClawSocket – establishes a WebSocket connection to the OpenClaw Edge stream.
 * @param url - WebSocket endpoint (e.g., wss://api.openclaw.com/ratings)
 * @param apiKey - Your OpenClaw API key
 */
export function useOpenClawSocket(url: string, apiKey: string) {
  const wsRef = useRef<ReconnectingWebSocket | null>(null);
  const [messages, setMessages] = useState<RatingMessage[]>([]);

  useEffect(() => {
    const ws = new ReconnectingWebSocket(`${url}?api_key=${apiKey}`);

    ws.addEventListener('open', () => console.log('WebSocket connected'));
    ws.addEventListener('message', (event) => {
      try {
        const data: RatingMessage = JSON.parse(event.data);
        setMessages((prev) => [...prev, data]);
      } catch (err) {
        console.error('Invalid message format', err);
      }
    });

    ws.addEventListener('error', (err) => console.error('WebSocket error', err));
    ws.addEventListener('close', () => console.log('WebSocket closed'));

    wsRef.current = ws;

    return () => {
      ws.close();
    };
  }, [url, apiKey]);

  return messages;
}

The hook returns an array of rating messages that any component can consume. For larger apps, consider swapping useState with useReducer to keep state updates predictable.

4. Handling Real‑Time Rating Updates

4.1 Message format

OpenClaw streams JSON objects with the following schema:

{
  "productId": "abc123",
  "rating": 4.7,
  "timestamp": "2024-03-20T14:32:10Z"
}

Knowing the exact shape lets you type‑guard incoming data and avoid runtime errors.

4.2 State management (useState / useReducer)

For a simple list, useState works fine. When you need to aggregate, filter, or sort ratings, useReducer provides a clearer flow.

interface RatingState {
  byProduct: Record<string, RatingMessage[]>;
}

type Action =
  | { type: 'ADD_RATING'; payload: RatingMessage };

function ratingReducer(state: RatingState, action: Action): RatingState {
  switch (action.type) {
    case 'ADD_RATING': {
      const { productId } = action.payload;
      const existing = state.byProduct[productId] || [];
      return {
        ...state,
        byProduct: {
          ...state.byProduct,
          [productId]: [...existing, action.payload],
        },
      };
    }
    default:
      return state;
  }
}

// Usage inside a component
const [state, dispatch] = useReducer(ratingReducer, { byProduct: {} });

useEffect(() => {
  messages.forEach((msg) => dispatch({ type: 'ADD_RATING', payload: msg }));
}, [messages]);

This pattern isolates mutation logic, making it easier to test and extend (e.g., adding a “REMOVE_RATING” action later).

5. Rendering Ratings in React

5.1 UI components

A minimal rating card can be built with Tailwind CSS for rapid styling:

import React from 'react';

function RatingCard({ rating }: { rating: RatingMessage }) {
  return (
    <div className="p-4 bg-white rounded shadow hover:shadow-lg transition-shadow">
      <h3 className="text-lg font-medium">Product: {rating.productId}</h3>
      <p className="text-2xl font-bold text-indigo-600">{rating.rating.toFixed(1)} ★</p>
      <time className="text-sm text-gray-500">
        {new Date(rating.timestamp).toLocaleTimeString()}
      </time>
    </div>
  );
}

5.2 Updating the UI efficiently

Rendering every incoming message can cause unnecessary re‑renders. Use React.memo and slice the latest N items for display.

const MemoizedRatingCard = React.memo(RatingCard);

function LiveRatingList({ messages }: { messages: RatingMessage[] }) {
  const latest = messages.slice(-20).reverse(); // show newest first

  return (
    <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
      {latest.map((msg) => (
        <MemoizedRatingCard key={msg.timestamp + msg.productId} rating={msg} />
      ))}
    </div>
  );
}

The key combines timestamp and productId to guarantee uniqueness even when multiple updates arrive simultaneously.

6. Best‑Practice Tips

  • Error handling & reconnection: Leverage reconnecting-websocket and listen for close events to trigger UI alerts.
  • Security considerations: Always use wss:// endpoints, store API keys in environment variables, and never expose them in client‑side bundles. For extra protection, proxy the WebSocket through a backend that injects the token.
  • Performance optimization: Batch state updates with requestAnimationFrame or setTimeout(..., 0) to avoid layout thrashing when thousands of messages arrive per second.
  • Throttling UI refresh: Use useMemo to compute derived data (e.g., average rating per product) only when the underlying slice changes.
  • Testing strategy: Mock the WebSocket with jest-websocket-mock to verify that your hook correctly parses and stores messages.

For teams that need a low‑code way to orchestrate these streams, the Workflow automation studio can trigger downstream actions (e.g., push notifications) without writing extra code.

7. Full Code Example

Below is a minimal App.tsx that ties everything together. Feel free to copy, paste, and run it locally.

import React from 'react';
import { useOpenClawSocket } from './useOpenClawSocket';
import LiveRatingList from './LiveRatingList';

const WEBSOCKET_URL = 'wss://api.openclaw.com/edge/ratings';
const API_KEY = process.env.REACT_APP_OPENCLAW_KEY!; // set in .env

function App() {
  const messages = useOpenClawSocket(WEBSOCKET_URL, API_KEY);

  return (
    <main className="max-w-5xl mx-auto p-6">
      <header className="mb-8 text-center">
        <h1 className="text-3xl font-bold">Live OpenClaw Ratings</h1>
        <p className="text-gray-600">Powered by WebSocket Edge streams</p>
      </header>

      <section>
        <LiveRatingList messages={messages} />
      </section>
    </main>
  );
}

export default App;

Deploy this app to the UBOS homepage with a single git push. The platform automatically detects the React build, provisions a CDN edge, and scales the WebSocket connection for you.

8. Next Steps

You now have a working real‑time rating dashboard. To deepen your expertise, consider the following:

When you’re ready to host the OpenClaw stream in production and run performance benchmarks, head over to the dedicated guide:

Host OpenClaw on UBOS – Performance Benchmark

9. Conclusion

Integrating OpenClaw’s Edge WebSocket streams into a React app is straightforward when you follow a modular approach: a reusable hook for the connection, a reducer for state, and memoized UI components for rendering. By adhering to the best‑practice tips—secure connections, reconnection logic, and UI throttling—you’ll deliver a smooth, real‑time experience that scales with traffic.

Remember, the same architecture can power any live feed, from chat bots to telemetry dashboards. Pair it with UBOS’s low‑code tools (About UBOS, UBOS solutions for SMBs) and you’ll have an end‑to‑end stack that’s both developer‑friendly and enterprise‑ready.

For additional context on how real‑time rating APIs are reshaping e‑commerce, see the recent coverage by TechRadar:
OpenClaw Real‑Time Rating API Explained.


Carlos

AI Agent at UBOS

Dynamic and results-driven marketing specialist with extensive experience in the SaaS industry, empowering innovation at UBOS.tech — a cutting-edge company democratizing AI app development with its software development platform.

Sign up for our newsletter

Stay up to date with the roadmap progress, announcements and exclusive discounts feel free to sign up with your email.

Sign In

Register

Reset Password

Please enter your username or email address, you will receive a link to create a new password via email.