Rxjs 在使用主题的反应文本输入组件上去抖动不会在无状态/功能组件上批量输入文本 [英] Rxjs debounce on react text input component using Subjects does not batch input text on stateless/functional component

查看:23
本文介绍了Rxjs 在使用主题的反应文本输入组件上去抖动不会在无状态/功能组件上批量输入文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试更深入地研究 rxjs 并发现了一个问题,即我尝试去抖动的输入字段在每次按键时都会调度一个事件,去抖动只保存输出但会生成如下树:

aas(延迟 - 等待 200 毫秒,然后同步触发其余部分)阿斯达自卫队asdfg....

相同的代码在类组件中按预期工作(https://stackoverflow.com/a/44300853/1356046) 但无法理解为什么它不适用于无状态组件.这是一个例子:https://stackblitz.com/edit/react-hzhrmf - 你可以看到每次击键都会触发 useState 更新.

非常感谢.

解决方案

React 不断调用你的函数来渲染组件.因此,Subject 会不断地重新创建.

使用带有 useState 的工厂来保留主题并使用 useEffect 确保订阅只进行一次应该可以解决您的问题.

像这样:

import React, { Component, useState, useEffect, useRef } from 'react';从'react-dom'导入{渲染};import { debounceTime, map, tap, distinctUntilChanged } from 'rxjs/operators';从 'rxjs' 导入 { fromEvent, Subject };导入'./style.css';const App = 道具 =>{const [queryName, setQueryName] = useState("");const [debouncedName, setDebouncedName] = useState("");const [onSearch$] = useState(()=>new Subject());useEffect(() => {const 订阅 = onSearch$.pipe(去抖动时间(400),distinctUntilChanged(),点击(a => console.log(a))).subscribe(setDebouncedName);}, [])const handleSearch = e =>{setQueryName(e.target.value);onSearch$.next(e.target.value);};返回 (<div><输入占位符=搜索标签"值={查询名称}onChange={handleSearch}/><p>去抖动:{debouncedName}</p>

);}render(<App/>, document.getElementById('root'));

I'm trying to dive deeper into rxjs and found an issue where the input field I'm trying to debounce dispatches an event on every keypress, the debounce only holds the output but results in a tree like:

a
as(delay - waits 200ms, then fires the rest synchronously)
asd
asdf
asdfg 
....

The same code works as expected in a class component(https://stackoverflow.com/a/44300853/1356046) but cannot understand why it doesn't work with stateless components. Here's an example: https://stackblitz.com/edit/react-hzhrmf - you can see the useState update fires for every keystroke.

Thanks a lot.

解决方案

React continuously calls your function to render the component. Therefore the Subject is continuously recreated.

Using a factory with useState to keep the subject and working with useEffect to make sure the subscription is only made once should fix your issue.

Something like this :

import React, { Component, useState, useEffect, useRef } from 'react';
import { render } from 'react-dom';
import { debounceTime, map, tap, distinctUntilChanged } from 'rxjs/operators';
import { fromEvent, Subject } from 'rxjs';

import './style.css';
const App = props => {
  const [queryName, setQueryName] = useState("");
  const [debouncedName, setDebouncedName] = useState("");
  const [onSearch$] = useState(()=>new Subject());
  useEffect(() => {
    const subscription = onSearch$.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      tap(a => console.log(a))
    ).subscribe(setDebouncedName);
  }, [])
  const handleSearch = e => {
    setQueryName(e.target.value);
    onSearch$.next(e.target.value);
  };

  return (
    <div>
      <input
        placeholder="Search Tags"
        value={queryName}
        onChange={handleSearch}
      />
      <p>Debounced: {debouncedName}</p>
    </div>
  );
}

render(<App />, document.getElementById('root'));

这篇关于Rxjs 在使用主题的反应文本输入组件上去抖动不会在无状态/功能组件上批量输入文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆