Skip to content
Track That Ride
Menu

Quickstart

React quickstart

This React quickstart shows one delivery on a live map. Use the @trackthatride/react-map component, or a small useDeliveryTracking hook that opens the delivery’s Server-Sent Events stream and keeps status, arrival time, driver and position in state. Both call Track That Ride’s public tracking endpoints directly from the browser, which allow cross-origin reads.

Using the SDK

@trackthatride/react-map 1.1.2 draws the delivery on a MapLibre map and keeps it live with @trackthatride/realtime:

// npm install @trackthatride/react-map maplibre-gl
import 'maplibre-gl/dist/maplibre-gl.css';
import { TrackingMap } from '@trackthatride/react-map';

export function DeliveryTracker({ token }) {
  // token is the delivery's public_tracking_token; apiBaseUrl defaults to https://trackthatride.com
  return <TrackingMap trackingCode={token} style={{ width: '100%', height: 420 }} />;
}

TrackingInfo and useTrackingSession are exported too, for showing the status and arrival time beside the map. On React Native, @trackthatride/react-native-map 1.1.0 does the same with react-native-maps.

Without the SDK: a hook and a map

  1. Install the map library: npm install react-leaflet leaflet
  2. Have a delivery’s public_tracking_token to hand (your server gets it when it creates the delivery).

1. The hook

// React hook: follow one Track That Ride delivery live, straight from the browser.
// No dependencies beyond React 18. `token` is the delivery's public_tracking_token (no API key).
// The public tracking endpoints allow cross-origin reads, so the hook calls Track That Ride directly.
// Optional: to proxy through your own server (examples/node/tracking-relay.mjs), set API = '/track'.
import { useEffect, useState } from 'react';

const API = 'https://trackthatride.com/api/public/track';

export function useDeliveryTracking(token) {
  const [state, setState] = useState({ status: null, eta: null, driver: null, position: null, updates: [], error: null });

  useEffect(() => {
    if (!token) return undefined;
    const url = `${API}/${encodeURIComponent(token)}`;
    const stream = new EventSource(`${url}/events`);

    stream.onmessage = (e) => {
      const msg = JSON.parse(e.data);
      setState((s) => {
        switch (msg.type) {
          case 'connected':
            return {
              ...s,
              status: msg.delivery.status,
              eta: msg.delivery.eta ?? s.eta,
              driver: msg.driver,
              position: msg.driver?.latitude != null ? { lat: msg.driver.latitude, lng: msg.driver.longitude } : s.position,
            };
          case 'driver_location':
            return { ...s, position: { lat: msg.location.latitude, lng: msg.location.longitude } };
          case 'ride_status_change':
            return { ...s, status: msg.status };
          case 'eta_update':
            return { ...s, eta: msg.eta };
          case 'ride_update':
            return { ...s, updates: [msg.update, ...s.updates] };
          default:
            return s; // heartbeat, reconnect, resync…
        }
      });
    };
    stream.onerror = () => {
      if (stream.readyState === EventSource.CLOSED) setState((s) => ({ ...s, error: 'This tracking link is not valid or has expired.' }));
    };
    return () => stream.close();
  }, [token]);

  return state;
}

2. The map component

// Show a delivery's driver on a map with react-leaflet (OpenStreetMap tiles, no API key).
//   npm install react-leaflet leaflet
import 'leaflet/dist/leaflet.css';
import { MapContainer, TileLayer, CircleMarker, useMap } from 'react-leaflet';
import { useEffect } from 'react';
import { useDeliveryTracking } from './useDeliveryTracking';

function FollowDriver({ position }) {
  const map = useMap();
  useEffect(() => {
    if (position) map.panTo([position.lat, position.lng]);
  }, [map, position]);
  return null;
}

export function DeliveryMap({ token }) {
  const { status, eta, driver, position, updates, error } = useDeliveryTracking(token);
  if (error) return <p>{error}</p>;

  return (
    <div>
      <p>
        {driver?.name ? `${driver.name} · ` : ''}
        {status ?? 'Connecting…'}
        {eta ? ` · arriving about ${new Date(eta).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}` : ''}
      </p>
      <MapContainer center={[51.5074, -0.1278]} zoom={13} style={{ height: 400 }}>
        <TileLayer url="https://tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="© OpenStreetMap contributors" />
        {position && <CircleMarker center={[position.lat, position.lng]} radius={10} />}
        <FollowDriver position={position} />
      </MapContainer>
      <ul>
        {updates.map((u) => (
          <li key={u.id}>{u.title}</li>
        ))}
      </ul>
    </div>
  );
}

3. Use it

<DeliveryMap token={order.trackingToken} />

Optional: proxy through your own server

Not needed, because the public tracking endpoints allow cross-origin reads. If you want the requests on your own domain, run the relay from the JavaScript quickstart at /track and set API = '/track' in the hook.

What we tested

Both example files compile with esbuild as part of our checks, and the hook’s message handling matches the stream format documented in real-time streams. @trackthatride/react-map is tested with a mocked map: pickup, drop-off and driver markers from the API’s fields, and the driver marker moving on each location update. The stream it uses, @trackthatride/realtime, was run end to end against a local copy of the API.

Frequently asked questions

Should I use the component or the hook?

Use @trackthatride/react-map (1.1.2) for a ready-made MapLibre map with pickup, drop-off and a moving driver marker. Use the hook when you want your own map library or your own layout; it only returns data.

Do I have to use Leaflet with the hook?

No. The hook only returns data. Draw the position with Google Maps, MapLibre, Mapbox or anything else; Leaflet with OpenStreetMap tiles is used here because it needs no API key.

Does it reconnect?

Yes. EventSource reconnects by itself and sends the last event ID, and the server replays what you missed. The SDK adds a growing back-off and a retry limit.

Can I use it with Next.js?

Yes, in a client component. The browser calls Track That Ride directly, so no API route is needed unless you choose to proxy.

Get an API key

Sign up free with no card, create a key under API keys, and run this example against your own account.

Sign-up happens on trackthatride.com.