0

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>
    </>
  );
};
Josh Pittman
  • 7,024
  • 7
  • 38
  • 66
  • If you downvote this question please explain why so I can improve it. I'm genuinely stuck, I would like to ask a better question, but I don't know enough about how this works to ask a better question yet. I've been looking online and all react/rxjs tutorials just use subjects without explaining why. – Josh Pittman Oct 14 '19 at 02:24

2 Answers2

3

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.

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • Thanks, Adrain. So I wanted to see if there was a way to do it without a subject because using next feels like I am messing with the internals of rxjs and I was hoping for a cleaner way to do such a simple task. Intuitively, it feels like overkill for such a simple piece of functionality. I will continue to use Subject then. Thank you. – Josh Pittman Oct 14 '19 at 07:25
  • Something needs to feed the stream for it to emit. Without something calling next on an observer somewhere then the observable is not going to emit. I have been using RxJs for over 2 years and I only hand rolled a few observable in the beginning. Since then every thing has been subjects, behavior subjects and combining them. I recently just got the RxJs badge on StackOverflow. – Adrian Brand Oct 14 '19 at 22:20
  • Is this outside of the context of React. Are you saying that subjects are bread and butter of working with rxjs or is it just in the context of React that you have to use subjects when something else might make more sense? – Josh Pittman Oct 15 '19 at 10:46
  • 1
    Subjects pretty much are the bread and butter of RxJs, we use them continually in Angular, most of the data in an Angular app gets stored in behavior subjects. – Adrian Brand Oct 15 '19 at 22:38
  • Why do so many introductory tutorials not cover them? They are presented as an additional/advanced thing you pick up once you have a firm grasp of observables. I'm not challenging your answer. I very grateful for your help. I'm just curious. I feel the like general coverage to relative importance ratio is off here. Or have I just been doing the wrong tutorials? – Josh Pittman Oct 16 '19 at 02:30
  • I suppose the things you are reading is about the fundamentals. Hand rolling an observable is definitely more advanced that using a subject. – Adrian Brand Oct 16 '19 at 03:19
  • But I'm just talking about capturing an onchange event from an input, how much more basic can it get? – Josh Pittman Oct 16 '19 at 04:07
0

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>
);