Skip to content

SSE ​

SSE live demo

Use the Framework picker in the header to filter stacks.

Core — api.sse ​

Framework

Core · tanstack-fetch/sse · works in every framework

Start the stream — real tanstack-fetch/sse against a mock text/event-stream (with Bearer token support).

Live demo · SSE

api.sse over fetch

Real tanstack-fetch/sse against a mock event stream — cookies / Authorization work (unlike EventSource).

Idle — start the stream

import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/react'

const api = createFetch({
  plugins: ['sse-resume'],
  getToken: () => localStorage.getItem('access_token'),
})

const OrdersLive = () => {
  const { data, status, error, close } = useSse<Tick>('/orders/stream', {
    client: api,
  })

  if (status === 'error') return <p>{error?.message}</p>
  return (
    <>
      <p>{status} · tick #{data?.n}</p>
      <button onClick={close}>Close</button>
    </>
  )
}

TanStack Start ​

Framework

TanStack Start · router route + useSse (browser)

tsx
import { createFileRoute } from '@tanstack/react-router'
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/react'

const api = createFetch({ plugins: ['sse-resume'] })

export const Route = createFileRoute('/orders/live')({
  component: () => {
    const { data, status, close } = useSse('/orders/stream', { client: api })
    return (
      <div>
        <p>{status}</p>
        <button type="button" onClick={close}>
          Stop
        </button>
      </div>
    )
  },
})

Remix ​

Framework

Remix · client-only useSse

Same React hook — mount in a client component, not in loader.

SolidStart ​

Framework

SolidStart · tanstack-fetch/solid

tsx
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/solid'

const api = createFetch({ plugins: ['sse-resume'] })
const { data, status, close } = useSse('/orders/stream', { client: api })

React useSse ​

Framework

React · tanstack-fetch/react

Pass { client: api } — FetchProvider is optional.

status: connecting | connected | disconnected | error.

Live demo · useSse

React useSse + status

Pass {'{ client: api }'} — no FetchProvider required. Status: connecting → connected → disconnected / error.

status: disconnected

import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/react'

const api = createFetch({
  baseUrl: import.meta.env.VITE_API_URL,
  plugins: ['sse-resume'],
  getToken: () => localStorage.getItem('access_token'),
})

const OrdersLive = () => {
  // Pass client — FetchProvider is optional
  const { data, status, error, close } = useSse<Tick>('/orders/stream', {
    client: api,
  })

  if (status === 'error') return <p>{error?.message}</p>

  return (
    <div>
      <p>{status}</p>
      <p>{data ? `#${data.n}` : '—'}</p>
      <button type="button" onClick={close}>Disconnect</button>
    </div>
  )
}
tsx
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/react'

const api = createFetch({
  plugins: ['sse-resume'],
  getToken: () => localStorage.getItem('access_token'),
})

const OrdersLive = () => {
  const { data, status, error, close } = useSse<OrderEvent>('/orders/stream', {
    client: api,
  })

  if (status === 'error') return <p>{error?.message}</p>

  return (
    <div>
      <p>{status}</p>
      <pre>{JSON.stringify(data, null, 2)}</pre>
      <button type="button" onClick={close}>
        Disconnect
      </button>
    </div>
  )
}

Vue / Nuxt useSse ​

Framework

Vue 3 / Nuxt · tanstack-fetch/vue

vue
<script setup lang="ts">
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/vue'

const api = createFetch({
  plugins: ['sse-resume'],
  getToken: () => localStorage.getItem('access_token'),
})

const { data, status, error, close } = useSse<OrderEvent>('/orders/stream', {
  client: api,
})
</script>

<template>
  <p v-if="status === 'error'">{{ error?.message }}</p>
  <div v-else>
    <p>{{ status }}</p>
    <pre>{{ data }}</pre>
    <button type="button" @click="close">Disconnect</button>
  </div>
</template>

Next.js ​

Framework

Next.js · tanstack-fetch/react (Client Component)

Same as React useSse — mark the component 'use client'. See SSE · Next.js.

Solid useSse ​

Framework

Solid · tanstack-fetch/solid

tsx
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/solid'

const api = createFetch({ plugins: ['sse-resume'] })

const OrdersLive = () => {
  const { data, status, error, close } = useSse<OrderEvent>('/orders/stream', {
    client: api,
  })

  return (
    <div>
      <p>{status()}</p>
      <pre>{JSON.stringify(data(), null, 2)}</pre>
      <button type="button" onClick={close}>
        Disconnect
      </button>
    </div>
  )
}

Angular useSse ​

Framework

Angular · tanstack-fetch/angular

ts
import { createFetch } from 'tanstack-fetch/sse'
import { useSse } from 'tanstack-fetch/angular'

const api = createFetch({ plugins: ['sse-resume'] })

const { data, status, error, close } = useSse<OrderEvent>('/orders/stream', {
  client: api,
})
// data / status / error are Angular signals

Svelte / SvelteKit useSse ​

Framework

Svelte · tanstack-fetch/svelte

svelte
<script lang="ts">
  import { createFetch } from 'tanstack-fetch/sse'
  import { useSse } from 'tanstack-fetch/svelte'

  const api = createFetch({ plugins: ['sse-resume'] })
  const { data, status, error, close } = useSse('/orders/stream', { client: api })
</script>

<p>{$status}</p>
<pre>{JSON.stringify($data, null, 2)}</pre>
<button type="button" on:click={close}>Disconnect</button>

Browser-only in SvelteKit — see Svelte guide.

Need two-way messages, WebTransport, or NDJSON? → WebSocket · WebTransport · NDJSON demos.

Guide: SSE · example: examples/sse-live (React)

MIT Licensed · Created by Mohammad Garmabi · Not an official TanStack package