Introduce to RxJS
- What is RxJS
- Why RxJS
- How to learn RxJS
- How could I use RxJS in React
- Introduce some tools articles and videos that can help you to know about RxJS
What is RxJS?
Questions I've asked:
- "WTH is this? another Lodash?"
- "What operator do I use for that?"
- "Why my Observable after concatMap never triggered?"
- "Why did that Observable die?"
- "What is this RxJS code I wrote 4 months ago really doing?"
Let's answer a few of these...
Thinking Reactive
Drag and drop for example
For each mousedown on your target, you start listening to mousemoves on the document until a single mouseup on document
Drag and drop
import { fromEvent } from 'rxjs'
const target = document.querySelector('#target')
const targetMouseDown$ =
fromEvent(target, 'mousedown')
const docMouseMove$ =
fromEvent(document, 'mousemove')
const docMouseUp$ =
fromeEvent(document, 'mouseup')
Drag and drop for example
For each mousedown on your target, you start listening to mousemoves on the document until a single mouseup on the document
Drag and drop
import { takeUntil } from 'rxjs/operators'
docMouseMove$.pipe(takeUntil(docMouseUp$))
Drag and drop for example
For each mousedown on your target, you start listening to mousemoves on the document until a single mouseup on the document.
Drag and drop
const dragDrop$ = targetMouseDown$.pipe(switchMap(
() => docMouseMove$.pipe(takeUntil(docMouseUp$))
))
Why RxJS?
RxJS is lodash for async
Actually RxJS is not for state management, it's a big mistake by some developers who were not familiar with RxJS.
We are still finding a best practice to compose our frontend techs, but it's okay to use RxJS in imperative way in your React Component.
Observable | Promise | |
---|---|---|
Task type | sync or async | async |
Scheduler | Execute on subscribe | Execute immediately |
Value | Empty or single or multiple | Single |
How to learn RxJS?
Start from the operator you already know.
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
const a$ = new Observable(observer => {
observer.next(1)
observer.complete()
})
const b$ = a$.pipe(
map(x => x + 1)
)
b$.subscribe((result) => {
console.log(result) // 2
})
Write your imperative codes in subscribe
const questions$ = query(this.questionQuery, queryArgs)
.subscribe(({ data, loading }) => {
// imperative codes
if (loading) {
this.setState({ loading: true })
} else {
this.setState({ questions: data.questions })
}
})
Learning RxJS
How could I use RxJS in React?
The lifecycle of Observable
class SomeComponent extends React.PureComponent {
state = {
question: null
}
get questionQuery () {
return gql`
${this.props.questionId}
whateverquery
`
}
clickGetQuestion$ = new Subject()
question$ = this.clickGetQuestion$.pipe( // setup Observables
skipWhile(() => !!this.state.question),
exhaustMap(() => rxFetch.query(this.questionQuery)),
tap((response) => {
this.setState({ question: response.data })
})
)
onClickGetQuestion = () => {
this.clickGetQuestion$.next() // push data into question$
}
componentDidMount() {
this.subscription = this.question$.subscribe() // start Observables in componentDidMount
}
componentWillUnmount() {
if (this.subscription) this.subscription.unsubscribe() // destroy Subscriptions in componentWillUnmount
this.clickGetQuestion$.complete()
}
render() {
return (
<div>
<button onClick={this.onClickGetQuestion}>Get question</button>
{ this.state.question.title }
</div>
)
}
}
Destroy Observable by takeUntil
class SomeComponent extends React.PureComponent {
state = {
question: null
}
get questionQuery () {
return gql`
${this.props.questionId}
whateverquery
`
}
clickGetQuestion$ = new Subject()
destroy$ = new Subject()
question$ = this.clickGetQuestion$.pipe( // setup Observables
skipWhile(() => !!this.state.question),
exhaustMap(() => rxFetch.query(this.questionQuery)),
takeUntil(this.destroy$), // destroyed once the this.destroy$ has value
tap((response) => {
this.setState({ question: response.data })
})
)
onClickGetQuestion = () => {
this.clickGetQuestion$.next() // push data into question$
}
componentDidMount() {
this.subscription = this.question$.subscribe() // start Observables in componentDidMount
}
componentWillUnmount() {
this.destroy$.next()
this.destroy$.complete()
this.clickGetQuestion$.complete()
}
render() {
return (
<div>
<button onClick={this.onClickGetQuestion}>Get question</button>
{ this.state.question.title }
</div>
)
}
}
Real world Observables in Our Project
RxJS materials.
- https://rxviz.com/ help you to understand the behavior of operators
- https://www.learnrxjs.io/ all operators guide and examples
- https://www.youtube.com/watch?v=AslncyG8whg&t=1s RxJS and redux-observable introduce from Netflix
- https://www.youtube.com/watch?v=JCXZhe6KsxQ&t=58s introducing RxJS 6 by Benlesh
Q & A
RxJS
By yinan
RxJS
- 723