react-rxbuilder
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

react-rxbuilder

Use rxjs Observable on react components, Inspiration comes from flutter's StreamBuilder

Install

$ npm i react-rxbuilder

Add two configurations to tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  },
}

use RxBuilder

import { useEffect, useState } from "react";
import { RxBuilder, ConnectionState } from "react-rxbuilder";
import { map, timer } from "rxjs";

export function TestPage() {
  const [timer$] = useState(
    timer(1000, 500).pipe(
      map((v) => {
        if (v === 20) throw `error number ${v}.`;
        return v;
      })
    )
  );

  useEffect(() => {
    return () => {
      timer$.subscribe();
    };
  }, []);

  return (
    <RxBuilder stream={timer$}>
      {(snap) => {
        console.log(snap.toString());

        if (snap.connectionState === ConnectionState.waiting) {
          return <p>loading...</p>;
        }

        if (
          snap.connectionState === ConnectionState.active ||
          snap.connectionState === ConnectionState.done
        ) {
          if (snap.hasError) return <p>{snap.error}</p>;

          if (!snap.hasData) return <p>not data</p>;

          return <p>{snap.data}</p>;
        }

        return null;
      }}
    </RxBuilder>
  );
}

use Subject

import { useState } from "react";
import { RxBuilder } from "react-rxbuilder";
import { BehaviorSubject, debounceTime } from "rxjs";

function IncBut(props: { count$: BehaviorSubject<number> }) {
  const inc = () => props.count$.next(props.count$.value + 1);
  return <button onClick={inc}>inc</button>;
}

export function TestPage() {
  const [count$] = useState(new BehaviorSubject<number>(0));
  const [count2$] = useState(count$.pipe(debounceTime(200)));

  useEffect(() => {
    return () => {
      count$.unsubscribe();
    };
  }, []);

  return (
    <>
      <RxBuilder stream={count2$}>
        {(snap) => {
          if (snap.hasData)
            return (
              <p>
                {snap.data}
                <IncBut count$={count$} />
              </p>
            );
          return null;
        }}
      </RxBuilder>

      <RxBuilder stream={count$}>
        {(snap) => {
          if (snap.hasData)
            return (
              <p>
                {snap.data}
                <IncBut count$={count$} />
              </p>
            );
          return null;
        }}
      </RxBuilder>
    </>
  );
}

Get asynchronous data

import { useState } from "react";
import { ConnectionState, RxBuilder } from "react-rxbuilder";
import { from, switchMap } from "rxjs";

export function TestPage() {
  const [json$] = useState(
    from(fetch("https://jsonplaceholder.typicode.com/todos/1")).pipe(
      switchMap((e) => e.json())
    )
  );
  return (
    <RxBuilder stream={json$}>
      {(snap) => {
        console.log(snap);
        
        if (snap.connectionState === ConnectionState.waiting)
          return <p>loading...</p>;

        if (snap.hasData) return <p>{JSON.stringify(snap.data)}</p>;

        return null;
      }}
    </RxBuilder>
  );
}

PromiseBuilder

import { ConnectionState, PromiseBuilder } from "react-rxbuilder";

export function TestPage() {
  return (
    <>
      <PromiseBuilder promise={Promise.resolve(1)}>
        {(snap) => {
          if (snap.hasData) return <p>{snap.data}</p>;
          return null;
        }}
      </PromiseBuilder>
      
      <PromiseBuilder promise={Promise.reject("error")}>
        {(snap) => {
          if (snap.hasError) return <p>{snap.error}</p>;
          return null;
        }}
      </PromiseBuilder>

      <PromiseBuilder
        promise={fetch("https://jsonplaceholder.typicode.com/todos/1").then(
          (r) => r.json()
        )}
      >
        {(snap) => {
          if (snap.connectionState === ConnectionState.waiting)
            return <p>loading...</p>;

          if (snap.hasError) return <p>Error: {snap.error}</p>;

          if (snap.hasData) return <p>{JSON.stringify(snap.data)}</p>;

          return null;
        }}
      </PromiseBuilder>
    </>
  );
}

RxService

Migrated to react-rxservice

Package Sidebar

Install

npm i react-rxbuilder

Weekly Downloads

5

Version

1.0.0

License

MIT

Unpacked Size

40.8 kB

Total Files

30

Last publish

Collaborators

  • ajanuw