草庐IT

javascript - RxJS 和 React 多次点击元素形成单个数据数组

coder 2024-07-26 原文

所以我刚开始尝试学习 rxjs 并决定在我目前正在使用 React 开发的 UI 上实现它(我有时间这样做,所以我就去做了)。然而,我仍然很难理解它实际上是如何工作的……不仅仅是“基本”的东西,比如什么时候实际使用 Subject 和什么时候使用 Observable,或者什么时候只使用 React 的本地状态,还有如何链接方法等等。但这太宽泛了,所以这是我遇到的具体问题。

假设我有一个 UI,其中有一个过滤器(按钮)列表,这些过滤器(按钮)都可以点击。每当我点击其中一个时,我首先要确保接下来的操作会去抖动(以避免太快和太频繁地发出网络请求),然后我想确保如果它被点击(事件),它将被插入一个数组,如果再次单击它,它将离开数组。现在,这个数组最终应该包括所有当前被点击或选择的按钮(过滤器)。

然后,当去抖时间结束时,我希望能够使用该数组并通过 Ajax 将它发送到我的服务器并用它做一些事情。

import React, { Component } from 'react';
import * as Rx from 'rx';

export default class CategoryFilter extends Component {
 constructor(props) {
    super(props);

    this.state = {
        arr: []
    }

    this.click = new Rx.Subject();
    this.click
    .debounce(1000)
    // .do(x => this.setState({
    //  arr: this.state.arr.push(x)
    // }))
    .subscribe(
       click => this.search(click),
       e => console.log(`error ---> ${e}`),
       () => console.log('completed')
    );
 }

search(id) {
    console.log('search --> ', id);
    // this.props.onSearch({ search });
}

clickHandler(e) {
    this.click.onNext(e.target.dataset.id);
}

render() {
    return (
        <section>
            <ul>
                {this.props.categoriesChildren.map(category => {
                    return (
                        <li
                            key={category._id}
                            data-id={category._id}
                            onClick={this.clickHandler.bind(this)}
                        >
                            {category.nombre}
                        </li>
                    );
                })}
            </ul>
        </section>
    );
 }
}

我可以在没有 RxJS 的情况下轻松地解决这个问题,我自己检查数组并使用一个小的去抖等等,但我选择这样做是因为我实际上想尝试理解它然后能够在更大的场景。但是,我必须承认我对最佳方法一无所知。这涉及很多方法和不同的东西(包括模式和库),我只是被困在这里。

无论如何,欢迎提供任何帮助(以及关于如何改进此代码的一般评论)。提前致谢!

--------------------------------更新----- ----------------------------

我已经在我的代码中实现了 Mark 的部分建议,但这仍然存在两个问题:

1- 我仍然不确定如何过滤结果,以便数组只保存被单击(和事件)的按钮的 ID。因此,换句话说,这些将是操作:

  • 点击一个按钮一次 -> 将其 ID 放入数组
  • 再次点击同一个按钮(可能是在第一次点击之后 单击或在任何其他时间)-> 从数组中删除其 ID。

这必须起作用才能通过 ajax 实际发送带有正确过滤器的数组。现在,我什至不确定这是否是 RxJS 的可能操作,但可以梦想......(另外,我愿意打赌它是)。

2- 也许这是一个更大的问题:当我在这个 View 中时,我如何才能真正维护这个数组。我猜我可以为此使用 React 的本地状态,只是不知道如何使用 RxJS 来实现。因为就目前而言,缓冲区仅返回在去抖动时间结束之前已被单击的按钮,这意味着它每次都“创建”一个新数组。这显然不是正确的行为。它应始终指向现有数组并过滤并使用它。

这是当前代码:

import React, { Component } from 'react';
import * as Rx from 'rx';

export default class CategoryFilter extends Component {
 constructor(props) {
    super(props);

    this.state = {
        arr: []
    }

    this.click = new Rx.Subject();
    this.click
    .buffer(this.click.debounce(2000))
    .subscribe(
        click => console.log('click', click),
        e => console.log(`error ---> ${e}`),
        () => console.log('completed')
    );
 }

search(id) {
    console.log('search --> ', id);
    // this.props.onSearch({ search });
}

clickHandler(e) {
    this.click.onNext(e.target.dataset.id);
}

render() {
    return (
        <section>
            <ul>
                {this.props.categoriesChildren.map(category => {
                    return (
                        <li
                            key={category._id}
                            data-id={category._id}
                            onClick={this.clickHandler.bind(this)}
                        >
                            {category.nombre}
                        </li>
                    );
                })}
            </ul>
        </section>
    );
 }
}

再次感谢大家!

最佳答案

使用 Rx.Observable.fromevent(参见 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/events.md#converting-a-dom-event-to-a-rxjs-observable-sequence)使您的过滤器项成为可观察的点击事件流 - 它理解用于点击处理的多元素选择器。

您希望一直接收点击事件,直到发生反跳(用户已启用/禁用她想要使用的所有过滤器)。您可以使用 Buffer operator为此,使用 closingSelector 需要在关闭缓冲区和发出缓冲值时发出一个值。

但留下了如何知道当前实际状态的问题。

更新

使用 .scan 运算符创建 filterState 数组并对其进行去抖动似乎要容易得多。

const sources = document.querySelectorAll('input[type=checkbox]');
const clicksStream = Rx.Observable.fromEvent(sources, 'click')
  .map(evt => ({
        name:  evt.target.name,
        enabled: evt.target.checked
  }));

const filterStatesStream = clicksStream.scan((acc, curr) => {
  acc[curr.name] = curr.enabled;
  return acc
}, {})
.debounce(5 * 1000)

filterStatesStream.subscribe(currentFilterState => console.log('time to do something with the current filter state: ', currentFilterState);

( https://jsfiddle.net/crunchie84/n1x06016/6/ )

关于javascript - RxJS 和 React 多次点击元素形成单个数据数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40392078/

有关javascript - RxJS 和 React 多次点击元素形成单个数据数组的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  5. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  8. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  9. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  10. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

随机推荐