1

Subscribing react state to an rxjs Observable is simple:

import React, { useState, useEffect } from 'react'
import * as r from 'rxjs'
import * as ro from 'rxjs/operators'

const obs$: r.Observable<number> = ...

const App = () => {
  const [count, setCount] = useState(0)
  useEffect(() => {
    const subscription = obs$.subscribe(setCount)
    return () => subscription.unsubscribe()
  }, [])
  return (...)
}

But what if my Observable depends on some react state and I don't want to re-subscribe every time it changes?

const App = () => {
  const [count, setCount] = useState(0)
  const [otherCount, setOtherCount] = useState(0)
  useEffect(() => {
    const subscription = obs$.pipe(
      ro.map(c => c + otherCount),
    ).subscribe(setCount)
    return () => subscription.unsubscribe()
  }, [otherCount]) // this will resubscribe every time `otherCount` changes
  return (...)
}

What if obs$ does something expensive every time it starts? Is there a safe way to do something like this without resubscribing every time otherCount changes?

AnthonyJoeseph
  • 223
  • 3
  • 10
  • Depending how exactly you want it to work, state changes could be made an observable, and then two of them could be combined with "zip". – Estus Flask Nov 03 '20 at 01:03

1 Answers1

1

The deeper issue here is event handling with react useEffect - SO post

I ended up going with this option from this answer for that post

const App = () => {
  const [count, setCount] = useState(0)
  const [otherCount, setOtherCount] = useState(0)
  const otherCountRef = useRef(otherCount)
  useEffect(() => {
    otherCountRef.current = otherCount
  }, [otherCount])
  useEffect(() => {
    const subscription = obs$.pipe(
      ro.map(c => c + otherCountRef.current),
    ).subscribe(setCount)
    return () => subscription.unsubscribe()
  }, [])
  return (...)
}
AnthonyJoeseph
  • 223
  • 3
  • 10