{"id":13887,"library":"react-native-sse","title":"React Native Server-Sent Events (SSE) Client","description":"react-native-sse provides a robust, native-friendly `EventSource` implementation for React Native applications, enabling Server-Sent Events (SSE) on both iOS and Android platforms. The current stable version is 1.2.1, with a demonstrated active release cadence focused on features and fixes, as seen in recent minor updates. A key differentiator is its use of `XMLHttpRequest` internally, which eliminates the need for additional native module implementations, simplifying installation and integration. The library fully supports TypeScript, ensuring type safety for event listeners and configuration. It's commonly utilized for real-time data synchronization with systems like Mercure and is compatible with modern streaming APIs, including those used for AI interactions like ChatGPT. Its design prioritizes ease of use and broad compatibility within the React Native ecosystem.","status":"active","version":"1.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/binaryminds/react-native-sse","tags":["javascript","react-native","expo","event-source","sse","server-sent-events","chatgpt","stream","ios","typescript"],"install":[{"cmd":"npm install react-native-sse","lang":"bash","label":"npm"},{"cmd":"yarn add react-native-sse","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-native-sse","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Recommended for consistent URL object behavior across React Native environments, particularly older ones, as standard URL object behavior can be inconsistent.","package":"react-native-url-polyfill/auto","optional":false}],"imports":[{"note":"The library is designed for modern JavaScript environments; ESM `import` is the preferred and widely adopted method in React Native projects. While CJS `require` might technically work in some setups, it is generally discouraged for new code.","wrong":"const EventSource = require('react-native-sse');","symbol":"EventSource","correct":"import EventSource from 'react-native-sse';"},{"note":"This is a TypeScript type definition used to strongly type event handler functions for better code safety and readability, especially when dealing with custom event types.","symbol":"EventSourceListener","correct":"import { EventSourceListener } from 'react-native-sse';"}],"quickstart":{"code":"import React, { useEffect, useState } from \"react\";\nimport { View, Text, StyleSheet } from \"react-native\";\nimport EventSource, { EventSourceListener } from \"react-native-sse\";\nimport \"react-native-url-polyfill/auto\"; // Use URL polyfill in React Native\n\n// Replace with your actual SSE server URL and token source\nconst SSE_SERVER_URL = \"https://demo.mercure.rocks/.well-known/mercure\";\nconst MOCK_HUB_TOKEN = process.env.MOCK_HUB_TOKEN ?? \"[your-actual-hub-token]\"; // Use process.env for secure token handling\n\ninterface Book {\n  id: number;\n  title: string;\n  isbn: string;\n}\n\nconst BookList: React.FC = () => {\n  const [books, setBooks] = useState<Book[]>([]);\n  const [connectionStatus, setConnectionStatus] = useState<string>(\"Connecting...\");\n  const [error, setError] = useState<string | null>(null);\n\n  useEffect(() => {\n    const url = new URL(SSE_SERVER_URL);\n    url.searchParams.append(\"topic\", \"/book/{bookId}\"); // Example topic\n\n    const es = new EventSource(url.toString(), {\n      headers: {\n        Authorization: {\n          toString: function () {\n            return \"Bearer \" + MOCK_HUB_TOKEN;\n          },\n        },\n      },\n      timeoutBeforeConnection: 5000, // Optional: Timeout for connection attempt\n    });\n\n    const listener: EventSourceListener = (event) => {\n      if (event.type === \"open\") {\n        console.log(\"SSE Connection Opened.\");\n        setConnectionStatus(\"Connected\");\n        setError(null);\n      } else if (event.type === \"message\") {\n        try {\n          const book = JSON.parse(event.data) as Book;\n          setBooks((prevBooks) => {\n            if (!prevBooks.some(b => b.id === book.id)) {\n              return [...prevBooks, book];\n            }\n            return prevBooks;\n          });\n          console.log(`Received book ${book.title}, ISBN: ${book.isbn}`);\n        } catch (parseError) {\n          console.error(\"Failed to parse message data:\", event.data, parseError);\n          setError(\"Failed to parse event data.\");\n        }\n      } else if (event.type === \"error\") {\n        console.error(\"Connection error:\", event.message);\n        setConnectionStatus(\"Disconnected with error\");\n        setError(event.message || \"Unknown connection error\");\n      } else if (event.type === \"exception\") {\n        console.error(\"Internal Error:\", event.message, event.error);\n        setConnectionStatus(\"Disconnected with exception\");\n        setError(event.message || \"Unknown exception\");\n      }\n    };\n\n    es.addEventListener(\"open\", listener);\n    es.addEventListener(\"message\", listener);\n    es.addEventListener(\"error\", listener);\n    es.addEventListener(\"close\", listener); // Listen to close events as well\n\n    return () => {\n      console.log(\"Cleaning up SSE connection.\");\n      es.removeAllEventListeners();\n      es.close();\n    };\n  }, []); // Empty dependency array ensures this runs once on mount/unmount\n\n  return (\n    <View style={styles.container}>\n      <Text style={styles.header}>Book Updates (SSE)</Text>\n      <Text>Status: {connectionStatus}</Text>\n      {error && <Text style={styles.errorText}>Error: {error}</Text>}\n      {books.length === 0 ? (\n        <Text>Waiting for book updates...</Text>\n      ) : (\n        books.map((book) => (\n          <View key={`book-${book.id}`} style={styles.bookItem}>\n            <Text style={styles.bookTitle}>{book.title}</Text>\n            <Text>ISBN: {book.isbn}</Text>\n          </View>\n        ))\n      )}\n    </View>\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    padding: 20,\n    backgroundColor: '#f5f5f5',\n  },\n  header: {\n    fontSize: 24,\n    fontWeight: 'bold',\n    marginBottom: 10,\n  },\n  bookItem: {\n    backgroundColor: '#ffffff',\n    padding: 15,\n    borderRadius: 8,\n    marginBottom: 10,\n    shadowColor: '#000',\n    shadowOffset: { width: 0, height: 1 },\n    shadowOpacity: 0.2,\n    shadowRadius: 1.41,\n    elevation: 2,\n  },\n  bookTitle: {\n    fontSize: 18,\n    fontWeight: '600',\n    marginBottom: 5,\n  },\n  errorText: {\n    color: 'red',\n    marginBottom: 10,\n  }\n});\n\nexport default BookList;","lang":"typescript","description":"This example demonstrates how to establish an SSE connection, configure authentication with a Bearer token, listen for `open`, `message`, `error`, and `close` events, parse incoming JSON data, manage component state with real-time updates, and ensure proper connection cleanup in a React Native functional component."},"warnings":[{"fix":"To ensure listeners always access the current state or props, either wrap the listener function in `useCallback` with appropriate dependencies, use a mutable ref (e.g., `useRef`) to hold the latest state, or retrieve the current state directly from a global state management solution like Redux within the listener callback.","message":"Event listeners defined as closures within React `useEffect` hooks can capture stale props or state from their initial render. This leads to unexpected behavior where the listener operates on outdated values, especially when trying to update state based on current data.","severity":"gotcha","affected_versions":"*"},{"fix":"Include `import 'react-native-url-polyfill/auto';` once at the entry point of your application (e.g., `index.js` or `App.tsx`) or wherever `URL` objects are constructed for SSE connection URLs.","message":"The standard `URL` object's behavior might not be fully consistent across all React Native environments or older Hermes/JavaScript engines. The library's examples and documentation recommend explicitly importing `react-native-url-polyfill/auto` to ensure robust URL parsing and manipulation.","severity":"gotcha","affected_versions":"*"},{"fix":"Upgrade to `react-native-sse` version `1.2.1` or newer to benefit from fixes ensuring correct `close` event dispatching and improved compatibility with various SSE server implementations (e.g., `sse-starlette`). Always ensure `es.close()` is explicitly called during component unmount or when the connection is no longer needed.","message":"Prior to version `1.2.1`, the `close` event might not have consistently dispatched in all scenarios, potentially leading to resource leaks or incorrect connection state management if relying solely on this event for cleanup. Issues related to text parsing with missing double newlines and alternative line endings were also addressed.","severity":"breaking","affected_versions":"<1.2.1"}],"env_vars":null,"search_vec":"'1.2.1':42 'activ':46 'addit':74 'ai':120 'android':35 'api':115 'applic':24 'broad':131 'cadenc':48 'chatgpt':123,151 'client':8 'common':97 'compat':111,132 'configur':94 'current':38 'data':103 'demonstr':45 'design':125 'differenti':62 'eas':127 'ecosystem':137 'elimin':70 'enabl':25 'ensur':87 'event':6,29,91,144,150 'event-sourc':143 'eventsourc':19 'expo':142 'featur':51 'fix':53 'focus':49 'friend':18 'fulli':84 'implement':20,77 'includ':116 'instal':79 'integr':81 'interact':121 'intern':68 'io':33,153 'javascript':138 'key':61 'librari':83 'like':107,122 'listen':92 'mercur':108 'minor':58 'modern':113 'modul':76 'nativ':2,11,17,23,75,136,141 'native-friend':16 'need':72 'platform':36 'priorit':126 'provid':13 'react':1,10,22,135,140 'react-nat':139 'react-native-ss':9 'real':101 'real-tim':100 'recent':57 'releas':47 'robust':15 'safeti':89 'seen':55 'sent':5,28,149 'server':4,27,148 'server-s':3,26 'server-sent-ev':147 'simplifi':78 'sourc':145 'sse':7,12,30,146 'stabl':39 'stream':114,152 'support':85 'synchron':104 'system':106 'time':102 'type':88 'typescript':86,154 'updat':59 'use':65,118,129 'util':98 'version':40 'within':133 'xmlhttprequest':67","created_at":"2026-04-20T01:56:49.620206+00:00","updated_at":"2026-04-20T01:56:49.620206+00:00","problems":[{"fix":"Verify the SSE server URL is correct and accessible. Ensure the server is running and configured to serve SSE (e.g., `Content-Type: text/event-stream` header) and that there are no cross-origin resource sharing (CORS) policies preventing your React Native app's domain from connecting.","cause":"The React Native client could not establish a network connection to the specified SSE server URL. This often indicates an incorrect URL, a server that is unreachable, network issues, or a server-side firewall/CORS configuration preventing the connection.","error":"TypeError: Network request failed"},{"fix":"Debug the SSE endpoint on the server side. Access the SSE URL directly in a web browser or using a tool like Postman to inspect the raw response. Ensure the server consistently sends `text/event-stream` with properly formatted SSE messages, ideally with JSON payloads if that is the expected data format.","cause":"The `message` event's `data` property, expected to be a JSON string, instead contains HTML or some other non-JSON text. This usually happens when the SSE endpoint is returning an error page or unexpected content from the server instead of valid SSE data.","error":"JSON Parse error: Unrecognized token '<' (or similar JSON parsing errors)"},{"fix":"To make the listener dynamic, use `useCallback` to memoize the listener and list all relevant state/props in its dependency array. Alternatively, if using a global state management system, access the current state directly from the store instance within the listener.","cause":"As described in warnings, a common React pattern where event listeners defined within `useEffect` hooks capture the component's state or props from the initial render, leading to stale closures. Subsequent renders with updated state do not automatically update the already-registered listener's scope.","error":"Event listener callback does not reflect latest state/props"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/binaryminds/react-native-sse","docs":null,"changelog":null,"pypi":null,"npm":"https://www.npmjs.com/package/react-native-sse","openapi_spec":null,"status_page":null,"smithery":null,"categories":["http-networking","web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-17","next_check":"2026-07-18","install_tag":null}}