I am new to Rxjs and am trying to learn how to integrate it with a simple React component without any external wrapper/library. I got this working here:
const counter = new Subject()
class App extends Component {
state = {
number: 0
}
componentDidMount() {
counter.subscribe(
val => {
this.setState({ number: this.state.number + val })
}
)
}
increment = () => {
counter.next(+1)
}
decrement = () => {
counter.next(-1)
}
render() {
return (
<div style={styles}>
Current number {this.state.number}
<br /> <br />
<button onClick={this.increment}>Plus</button>
<button onClick={this.decrement}>Minus</button>
</div>
)
}
https://codesandbox.io/s/02j7qm2xw
I trouble is that this uses Subjects which is a known anti-pattern according to experts like Ben Lesh: https://medium.com/@benlesh/on-the-subject-of-subjects-in-rxjs-2b08b7198b93
I tried doing this:
var counter = Observable.create(function (observer) {
// Yield a single value and complete
observer.next(0);
// Any cleanup logic might go here
return function () {
console.log('disposed');
}
});
class App extends Component {
state = {
number: 0
}
componentDidMount() {
counter.subscribe(
val => {
this.setState({ number: this.state.number + val })
}
)
}
increment = () => {
counter.next(+1)
}
decrement = () => {
counter.next(-1)
}
// - render
}
But this fails with the error: counter.next is not a function
So How would I use new Observable()
or Observable.create()
and use it to setState
with a plain React component?
Compared to other alternatives like Redux, I've found the use of RxJS and Hooks to be a really effective and straightforward way to manage state in React applications.
You can do it on the component itself, or on it's parent and pass the value to it as props. A good practice is to handle the unsubscription on the componentWillUnmount event using the takeUntil operator and a Subject: unmount$ = new Subject() //component class property componentDidMount() { //if using rxjs 6: window.
Observables are data source wrappers and then the observer executes some instructions when there is a new value or a change in data values. The Observable is connected to the observer who does the execution through subscription, with a subscribe method the observer connects to the observable to execute a code block.
Because .next()
is an Observer
's method, NOT Observables
.
The reason why Subject
works simply because Subject
itself is both an observer
and an observable
. When you call subject.next()
, you are simply just updating the observable
part, and notify all the observers
about the change.
It can be quite confusing sometimes when comes to Observable
and Observers
. To make it simple, think of this way: Observable
is someone who produces the data, a.k.a. data producers; while Observer
is someone who consume the data, a.k.a. data consumer. In a simple analogy, consumer eats what is produced. For the same token, Observer(consumer) observes(eats) the observable (produced).
In your context (or at least React/Redux paradigm), Subject
works better. That is because Subject
has state. It keep tracks of the value over the production of data (job of the Observable
). Every time the observable (the one inside Subject) changes, or update, any observers
that subscribes to the Subject
will get notified. See the pattern similar to redux here? Every time your redux store is updated, your view gets notified (and hence updated). In fact, if you are very used to reactive programming, you can eliminate the use of redux store completely, and fully replace them by Subject
s and/or BehaviourSubject
s.
For the post from Ben Lesh, he is merely stating this: Always use an Observable
if possible, only use Subject
when it is really needed. In that particular post, he is stating that a click event can just be an Observable
; using Subject
will be inappropriate. However, in your context, which is react/redux, using Subject
is fine - because the Subject
is used to keep track of the state of the store, and NOT the click event handler.
TLDR:
Subject
if you want to keep track of a state of a variable.next()
is Observer
's method, not Observable
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With