The bulk of this problem is that I'm trying to create react components that each have an observable based on the component's props. I have several locations, each with environmental readings, that I would like to independently generate D3 graphs for using RxJS to manage data coming in.
I have a working version of this concept here:
https://www.lloydrichardsdesign.com/experiment/021
The problem I'm having is with this example, I've hardcoded the firestore observable outside of the component. But in my next version, I would like to make a component that can feed in the locationId to the observable when it loads and then each component manage their own state.
This looks like:
import { Observable } from "rxjs"
import { Dispatch, SetStateAction, useEffect, useState } from "react";
const useObservable = (observable: Observable<any>, setter: Dispatch<SetStateAction<any>>) => {
useEffect(()=>{
let subscription = observable.subscribe(result => {
setter(result);
});
return ()=> subscription.unsubscribe()
},[observable, setter])
}
const LocationItem: React.FC<LocationProps> = ({ location }) => {
const [readings, setReadings] = useState<Array<Reading>>([]);
const dataObservable = collectionData(
db
.collection('mimirReading')
.where('locationId', '==', location.id)
.orderBy('timestamp', 'desc')
.limit(48)
);
useObservable(dataObservable, setReadings);
return(
<ol>
{readings.map(r=><li>{r.timestamp}</li>)}
</ol>
)
}
The problem is, this results in the useObservable being called over and over and over again never giving back any data. I end up with an empty readings state and my console going crazy.
I figured, I had to create the dataObservable when the component first mounts, so in useEffect, but then I would get errors related to calling useEffect inside itself. And lastly I tried pulling the subscription out and into the useEffect when first creating the component, but then the observable never collected any information.
Like so:
useEffect(() => {
const dataObservable = collectionData(
db
.collection('mimirReading')
.where('locationId', '==', location.id)
.orderBy('timestamp', 'desc')
.limit(48)
).subscribe((reads) => {
console.log(reads);
setReadings(reads as Array<Reading>);
});
console.log(dataObservable);
return () => dataObservable.unsubscribe();
}, []);
I'm at a bit of a loss now and don't know what to do. If anyone has any ideas or solutions it would be very much appreciated!