Josh Pittman
Josh Pittman

Reputation: 7324

RXJS in React without Subjects

I'm slowly picking up RXJS and learning how to use it in the context of React.

All the Rxjs tutorials I have found start off with observables. This makes sense. When I try and use an observable in react it doesn't work. I have to create a subject instead and push values into the subject.

Why is this the case? Why can't I use plain old observables in React? Am I doing something wrong? Can someone please explain why RXJS in react necessitates using subjects.

I realise this is a bit vague, but I don't yet understand the concepts to formulate a better question. Here is an example to illustrate what I am struggling to understand.

Here is a super simple component that takes a value in input value and displays it. regular react, no RXJS.

const InputBox = () => {
  const [value, setValue] = React.useState('');
  return (
    <>
      <p>{value}</p>
      <input value={value} onChange={e => setValue(e.target.value)}></input>
    </>
  );
};

If I want to do the same thing with RXJS, this works...

const inputStream$ = new Subject();

const InputBox = () => {
  const [value, setValue] = React.useState('');

  React.useEffect(() => {
    const subscription = inputStream$.subscribe(_value => setValue(_value));
    return () => subscription.unsubscribe();
  }, []);

  return (
    <>
      <p>{value}</p>
      <input
        value={value}
        onChange={e => inputStream$.next(e.target.value)}
      ></input>
    </>
  );
};

But if I try using a regular observable, no subject, then it doesn't work.

const inputStream$ = new Observable();

const InputBox = () => {
  const [value, setValue] = React.useState('');

  React.useEffect(() => {
    const subscription = inputStream$.subscribe(_value => setValue(_value));
    return () => subscription.unsubscribe();
  }, []);

  return (
    <>
      <p>{value}</p>
      <input
        value={value}
        onChange={e => inputStream$.next(e.target.value)}
      ></input>
    </>
  );
};

Upvotes: 0

Views: 968

Answers (2)

Rudi Jansen van Vuuren
Rudi Jansen van Vuuren

Reputation: 455

Please refer to this answer. You can simply use the Async component and pass it your observables.

return (
    <Async select={[names$]}>
        {result => <div>{result}</div>}
    </Async>
);

Upvotes: 0

Adrian Brand
Adrian Brand

Reputation: 21638

The next method exists on the observer, not the observable. A subject is both an observer and an observable, hence it has a next method. If you want to use a vanilla observable you need to pass the observer into the constructor. But why not use a subject, that is what they are for. A subject is also multicast so different components can subscribe to the same data more efficiently than with a plain observable.

Upvotes: 3

Related Questions