为了账号安全,请及时绑定邮箱和手机立即绑定

React 功能组件中的 RxJS

React 功能组件中的 RxJS

HUWWW 2023-02-24 16:03:29
这个问题的大部分是我正在尝试创建反应组件,每个组件都有一个基于组件道具的可观察对象。我有几个位置,每个位置都有环境读数,我想独立生成 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();  }, []);我现在有点茫然,不知道该怎么办。如果有人有任何想法或解决方案,将不胜感激!
查看完整描述

1 回答

?
LEATH

TA贡献1936条经验 获得超7个赞

保持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;

};

这样你就不需要外部状态设置器,它总是在钩子内处理。您还可以使用setStatewithinuseObservable来捕获可观察对象的错误和完成事件。


查看完整回答
反对 回复 2023-02-24
  • 1 回答
  • 0 关注
  • 153 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号