[英]RxJS inside React Functional Component
這個問題的大部分是我試圖創建反應組件,每個組件都有一個基於組件道具的可觀察對象。 我有幾個位置,每個位置都有環境讀數,我想獨立生成 D3 圖以使用 RxJS 來管理傳入的數據。
我在這里有一個這個概念的工作版本:
https://www.lloydrichardsdesign.com/experiment/021
我遇到的問題是在這個例子中,我在組件外部對 firestore observable 進行了硬編碼。 但是在我的下一個版本中,我想制作一個組件,該組件可以在加載時將 locationId 提供給 observable,然后每個組件管理自己的狀態。
這看起來像:
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>
)
}
問題是,這導致 useObservable 被一遍又一遍地調用,從不返回任何數據。 我最終得到一個空的讀數狀態,我的控制台發瘋了。
我想,我必須在組件第一次掛載時創建 dataObservable,所以在 useEffect 中,但是我會得到與在其內部調用 useEffect 相關的錯誤。 最后,我嘗試在第一次創建組件時將訂閱拉出並放入 useEffect,但隨后可觀察對象從未收集任何信息。
像這樣:
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();
}, []);
我現在有點不知所措,不知道該怎么辦。 如果有人有任何想法或解決方案,將不勝感激!
保持useObservable
鈎子隔離,並創建一個可觀察值(記憶到位置 id)以傳遞給它:
const useObservable = (observable, setter) => {
useEffect(() => {
let subscription = observable.subscribe(result => {
setter(result);
});
return () => subscription.unsubscribe()
},
[observable, setter]
);
};
const LocationItem = ({ location }) => {
const [readings, setReadings] = useState([]);
const dataObservable = useMemo(() => {
return collectionData(
db
.collection('mimirReading')
.where('locationId', '==', location.id)
.orderBy('timestamp', 'desc')
.limit(48)
);
}, [location.id]);
useObservable(dataObservable, setReadings);
return (
<ol>
{readings.map((r) => (
<li>{r.timestamp}</li>
))}
</ol>
);
};
或者,我還建議將狀態的所有權更改為useObservable
:
const useObservable = (observable) => {
const [value, setValue] = useState();
useEffect(() => {
let subscription = observable.subscribe((result) => {
setValue(result);
});
return () => subscription.unsubscribe();
}, [observable]);
return value;
};
這樣你就不需要外部狀態設置器,它總是在鈎子內處理。 您還可以在useObservable
使用setState
來捕獲 observable 的錯誤和完成事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.