簡體   English   中英

React 函數式組件中的 RxJS

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM