繁体   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