React Props Stream Utilities
react-props-stream is a utility library designed to bridge RxJS reactive streams with React components. It offers three primary mechanisms: `withPropsStream` (a Higher-Order Component), `streamingComponent` (a functional component constructor), and `WithObservable` (a render prop component), all enabling the declaration of component props or children based on Observable streams. The current stable version is 1.0.1, which introduced updates for TypeScript 4 and ES Module exports. While not frequently updated, it provides a stable and specialized approach for managing complex, asynchronous component logic using RxJS operators. Its key differentiation lies in providing a declarative, stream-based API for React, conceptually similar to patterns found in `recompose` but with a direct and focused integration with the RxJS ecosystem. It allows for efficient handling of data fetching, derived state, and animated values without relying solely on React's internal state management for all asynchronous operations.
Common errors
-
TypeError: (0 , rxjs_1.timer) is not a function
cause Mismatch in RxJS version, or incorrect import path for RxJS operators/creators (e.g., trying to import `timer` from `rxjs/operators` instead of `rxjs`).fixVerify that `rxjs@^6` is installed and that imports follow the RxJS v6 pattern: `import { timer } from 'rxjs'` for creation functions and `import { map } from 'rxjs/operators'` for operators. -
Error [ERR_REQUIRE_ESM]: require() of ES Module ...react-props-stream/dist/index.js from ... is not supported.
cause Attempting to import `react-props-stream` using CommonJS `require()` syntax in a Node.js or bundler environment that expects ES Modules.fixConfigure your project to use ES Modules (e.g., set `"type": "module"` in `package.json`) or switch to ES Module import syntax: `import { withPropsStream } from 'react-props-stream'`. -
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
cause Passing an invalid component type to `withPropsStream` or `streamingComponent`, or incorrect usage of the HOC where the wrapped component is not a valid React element.fixEnsure the argument provided as the `BaseComponent` to `withPropsStream` or the component returned by `streamingComponent`'s observable is a valid React functional or class component. -
Invariant Violation: Objects are not valid as a React child (found: object with keys {number}). If you meant to render a collection of children, use an array instead.cause When using the `WithObservable` component, the render prop function is trying to directly render an object emitted by the observable rather than a primitive value or a React element.fixEnsure the render prop function of `WithObservable` explicitly extracts and renders a valid React child (e.g., a string, number, or React element) from the observable's emission: `<WithObservable observable={num$} >{({ number }) => <div>{number}</div>}</WithObservable>`.
Warnings
- breaking The package transitioned to ES Modules (ESM) exclusively since version 1.0.1. Projects configured for CommonJS (CJS) will encounter import errors.
- breaking The dependency on `recompose` was removed in v1.0.1. While `react-props-stream` was inspired by `recompose`, projects implicitly relying on `recompose` being a transitive dependency may experience issues.
- gotcha The library peer-depends on `rxjs@^6`. Using newer versions of RxJS (v7, v8+) might introduce compatibility issues or require adapting import paths and operators, as RxJS has undergone breaking changes across major versions.
- gotcha The library requires React version `'>=16'`. Using older React versions will result in runtime errors.
Install
-
npm install react-props-stream -
yarn add react-props-stream -
pnpm add react-props-stream
Imports
- withPropsStream
const { withPropsStream } = require('react-props-stream')import { withPropsStream } from 'react-props-stream' - streamingComponent
const streamingComponent = require('react-props-stream').streamingComponentimport { streamingComponent } from 'react-props-stream' - WithObservable
const WithObservable = require('react-props-stream').WithObservableimport { WithObservable } from 'react-props-stream' - createEventHandler
const createEventHandler = require('react-props-stream').createEventHandlerimport { createEventHandler } from 'react-props-stream'
Quickstart
import React from 'react';
import ReactDOM from 'react-dom/client';
import { withPropsStream } from 'react-props-stream';
import { timer } from 'rxjs';
import { map } from 'rxjs/operators';
// Create an observable that emits an object { number: n } every second
const numbers$ = timer(0, 1000).pipe(
map(n => ({ number: n }))
);
// Define a simple functional component that displays a number prop
const DisplayNumber = (props: { number: number }) => (
<div>The number is {props.number}</div>
);
// Wrap the component with withPropsStream to inject props from the observable
const MyStreamingComponent = withPropsStream(
numbers$,
DisplayNumber
);
// Render the streaming component into the DOM
const rootElement = document.getElementById('root');
if (rootElement) {
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<MyStreamingComponent />
</React.StrictMode>
);
}
// To run this, ensure you have an HTML file with `<div id="root"></div>`