React 功能组件中的 RxJS

这个问题的大部分是我正在尝试创建反应组件,每个组件都有一个基于组件道具的可观察对象。我有几个位置,每个位置都有环境读数,我想独立生成 D3 图以使用 RxJS 管理传入的数据。


我在这里有这个概念的工作版本:


https://www.lloydrichardsdesign.com/experiment/021


我遇到的问题是这个例子,我已经硬编码了组件外部的 firestore observable。但在我的下一个版本中,我想制作一个组件,该组件可以在加载时将 locationId 提供给可观察对象,然后每个组件管理自己的状态。


这看起来像:


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();

  }, []);

我现在有点茫然,不知道该怎么办。如果有人有任何想法或解决方案,将不胜感激!


HUWWW
浏览 154回答 1
1回答

LEATH

保持useObservable钩子隔离,并创建一个可观察值(记忆到位置 id)以传递给它:const useObservable = (observable, setter) => {&nbsp; useEffect(() => {&nbsp; &nbsp; let subscription = observable.subscribe(result => {&nbsp; &nbsp; &nbsp; setter(result);&nbsp; &nbsp; });&nbsp; &nbsp; return () => subscription.unsubscribe()&nbsp; &nbsp; },&nbsp; &nbsp; [observable, setter]&nbsp; );};const LocationItem = ({ location }) => {&nbsp; const [readings, setReadings] = useState([]);&nbsp; const dataObservable = useMemo(() => {&nbsp; &nbsp; return collectionData(&nbsp; &nbsp; &nbsp; db&nbsp; &nbsp; &nbsp; &nbsp; .collection('mimirReading')&nbsp; &nbsp; &nbsp; &nbsp; .where('locationId', '==', location.id)&nbsp; &nbsp; &nbsp; &nbsp; .orderBy('timestamp', 'desc')&nbsp; &nbsp; &nbsp; &nbsp; .limit(48)&nbsp; &nbsp; );&nbsp; }, [location.id]);&nbsp; useObservable(dataObservable, setReadings);&nbsp; return (&nbsp; &nbsp; <ol>&nbsp; &nbsp; &nbsp; {readings.map((r) => (&nbsp; &nbsp; &nbsp; &nbsp; <li>{r.timestamp}</li>&nbsp; &nbsp; &nbsp; ))}&nbsp; &nbsp; </ol>&nbsp; );};或者,我进一步建议将状态的所有权更改为useObservable:const useObservable = (observable) => {&nbsp; const [value, setValue] = useState();&nbsp; useEffect(() => {&nbsp; &nbsp; let subscription = observable.subscribe((result) => {&nbsp; &nbsp; &nbsp; setValue(result);&nbsp; &nbsp; });&nbsp; &nbsp; return () => subscription.unsubscribe();&nbsp; }, [observable]);&nbsp; return value;};这样你就不需要外部状态设置器,它总是在钩子内处理。您还可以使用setStatewithinuseObservable来捕获可观察对象的错误和完成事件。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript