React 如何订阅在另一个组件中声明的可观察对象

Posted

技术标签:

【中文标题】React 如何订阅在另一个组件中声明的可观察对象【英文标题】:React How to subscribe for observables which is declared in another component 【发布时间】:2019-11-03 02:31:50 【问题描述】:

我正在尝试开发一个搜索框,它可以在用户键入时在弹出窗口中过滤搜索结果。我的代码示例如下。

class Search extends React.Component 
  constructor(props)  ... 

  onInputClick() 
    this.setState(...this.state, openResult: true);
  

  onInputBlur() 
    this.setState(...this.state, openResult: false);
  

  render() 
    return 
       <div id='search'>
         <Input onClick = this.onInputClick onBlur = this.onInputBlur />
         <Results open=this.state.open />
       </div>
    
  

&lt;Input /&gt; react 组件中,我对&lt;input /&gt; 使用了 onClick 和 onBlur。因此,当用户点击入/出时,整个&lt;Search /&gt; 组件会重新渲染,并且基于this.state.open 的值,GUI 会显示/隐藏结果。

现在我的问题是我在&lt;Input /&gt; 组件中声明了let input$ = Rx.fromEvent(ref, 'input')。如何过滤&lt;Result /&gt; 中的结果?

我的一个解决方案是像 input$.subscribe(data =&gt; updateReduxState(data)); 这样使用 Redux。当状态改变时,&lt;Result /&gt; 组件被重新渲染。

首先,它是否正确?其次,是否过度杀伤/过度工程?这样使用 Redux + Rxjs 太复杂了。

【问题讨论】:

您可以在输入中添加onChange 属性并将其连接到该组件内的可观察对象 我建议在这种情况下不要使用 observables,而只使用 redux,redux 已经为您提供了通过 dispatch 重新渲染组件的触发器。 您应该使用普通的onChange 处理程序并仅在您需要使用 RxJs 操作符(例如 distinctUntilChangeddebounceTimetakeWhile)执行流式操作时通过主题发出它等 【参考方案1】:

您的解决方案似乎没问题。我将使用 RxJS 主题 提供纯 RxJS 替代方案。假设您有两个组件,搜索组件包含您的&lt;input&gt;,结果组件显示基于搜索关键字的数据。

__________        __________
| search |        | result |
|        |   -->  |        |
|________|        |________|

您可以做的是,创建一个 subject 并根据您的要求在模糊或键上通过它发出值。 让结果组件订阅该主题并监听值。 根据搜索框中的关键字运行评估结果的功能并将其显示在结果组件中。 这样你就消除了 redux。

伪代码可以是,

searchComponent

searchboxSubject = new Subject<any>();

blurOut(event) 
   this.searchboxSubject.next(event); //event holds your search keyword.

resultComponent

searchboxSubject.subscribe((data) => this.evaluateResultAndUpdateUI(data));

【讨论】:

理论上是正确的。但是,我的问题是如何从另一个组件订阅。 我来自 Angular 背景,因此,我将创建一个服务。在该服务中,我将定义 rxjs 主题。searchSubject = new Subject(); 在两个组件中注入该服务。在搜索组件中使用主题发送搜索关键字myservice.searchSubject.next(keyword)。在结果组件中,使用主题来监听值并评估结果 `myservice.searchSubject.subscribe();。我相信 React 中也一定有服务概念。【参考方案2】:

最后,我没有使用这种方法input$.subscribe(data =&gt; updateReduxState(data))。相反,我只使用 setState() 作为父组件。只是回顾一下,input$ 在组件中声明,所以我需要像这样传递 onChange 处理程序&lt;Input onChange=Search.onChange() /&gt;

我的代码运行良好。我的朋友也喜欢搜索框。你可以在这里试一试:https://gokien.info/all-forums

【讨论】:

以上是关于React 如何订阅在另一个组件中声明的可观察对象的主要内容,如果未能解决你的问题,请参考以下文章

我们是不是需要取消订阅完成/错误输出的可观察对象?

如何取消订阅角度组件中的多个可观察对象?

如何对服务中的 BehaviorSubject 变量进行单元测试,它是组件中的可观察对象

不需要的可观察服务订阅

渲染在另一个组件的渲染函数中声明的组件不包括对 REACT 17 中 componentDidMount 方法的更改

避免在循环中使用嵌套的可观察订阅的正确方法是啥?