DEV Community

Cover image for What React RxJS libs do You Use?
Kostia Palchyk
Kostia Palchyk

Posted on • Edited on

What React RxJS libs do You Use?

I'm currently using redux-observable for effects. It fits nice into whole redux flow (the question is if I need Redux itself, but that's a separate matter)

Sometimes I use RxJS directly in an effect hook (surely, with teardown!), but there are RxJS hook libraries for that, e.g.: re-rxjs/react-rxjs, crimx/observable-hooks and LeetCode-OpenSource/rxjs-hooks (they have thousands of weekly downloads! Alas, I haven't tried them well yet)

And I made a tiny React + RxJS package to display Observable content:

import React from 'react';
import { $ } from 'react-rxjs-elements';

function App(){
  return <div>
    <$>{ timer(0, 1000) } sec</$>
  </div>
}
Enter fullscreen mode Exit fullscreen mode
npm i react-rxjs-elements

P.S. I also created an ⚠️ experimental JSX + RxJS framework — it's cute, check it out!

And what RxJS + React addons do you use?
How do you like them? Share an example!
Do you think we even need RxJS in React?

I'm listening

Share your thoughts!

Top comments (3)

Collapse
 
wolfhoundjesse profile image
Jesse M. Holmes • Edited

If I wanted to return an array of JSX, is there a better way than:

const api1$ = useMemo(() => 
  fromFetch('http://api1.dev').pipe(
    mergeMap(res => res.json())
  ),[])

const api2$ = useMemo(() => 
  fromFetch('http://api2.dev').pipe(
    mergeMap(res => res.json())
  ),[])

const services$ = useMemo(() =>
  forkJoin([api1$, api2$])
),[])

return <$>{ services$.pipe(
  map(items => items.map(
    item => <p key={item.id}> {item.description} </p>
  ))
)}
</$>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kosich profile image
Kostia Palchyk • Edited

Hey, Jesse!

Great question, a lot happening here :)

First, about observables inside render fn:

useMemo is fine, but it does not guarantee that the content will be preserved. Consider either using some useConst analogue, or moving Observables outside the render function.

const Component = () => {
  let time$ = useConst(() => timer(0, 1000));

  return <$div>{ timer$ }</$div>
};
Enter fullscreen mode Exit fullscreen mode

Also, check out this experimental update to the <$> library:

const Component = createComponent$(() => {
  let time$ = timer(0, 1000);

  return <$div>{ timer$ }</$div>
});
Enter fullscreen mode Exit fullscreen mode

The component function is executed only once, thus making it safe to create Observables here. This is a beta feature and I'm currently testing it. It's available in the @next npm version and can be trialled online More details at github/react-rxjs-elements/pull/9

Second, the double mapping

The services$.pipe( map(items => items.map( … thing always bothered me. There are also several solutions to it.

1: Use a separate component to render the list

function App() {
  let source$ = useConst(() => getData('/url/to/data'));

  return <$>{
    source$.pipe(
      map(response => <List items={response}/>)
    )
  }</$>
}
Enter fullscreen mode Exit fullscreen mode

2: Use rxjs-proxify to do the array.map in a more concise way:

export function App() {
  let source = useConst(() => proxify(getData('/url/to/data')));

  return <ul>
    <$>{
      source.map(i =>
        <li key={i.key}>{i.title}</li>
      )
    }</$>
  </ul>;
}
Enter fullscreen mode Exit fullscreen mode
Try this example in online playground

Proxify provides magic like proxify( of(42) ).toString() which returns an Observable<string>. So .map(…) in the example above creates another Observable, by calling .pipe(map( items => items.map(…) )) on the underlying Observable. More on the rxjs-proxify here

-

And just a side note: use ajax from rxjs/ajax to remove the

fromFetch('http://api2.dev').pipe(
  mergeMap(res => res.json())
);
// ≈
ajax('http://api2.dev');
Enter fullscreen mode Exit fullscreen mode

-

If that doesn't suit your needs — be sure to checkout other libs I mention, they are all pretty amazing.

Cheers 🙂

Collapse
 
kosich profile image
Kostia Palchyk • Edited

Some honorable mentions:

<Stream source={source$}>
  {values => <div>{values.message}</div>}
</Stream>

  • refract

Handle your component effects and side-effects in a clear and declarative fashion by using asynchronous data streams (reactive programming).

github.com/fanduel-oss/refract


Cool "implement it from scratch" tutorial on using React with RxJS