2

I have a simple click event with React function component and I try to throttle with RxJS throttleTime. Every click I throttle in 500ms but it seems like throttle never work at all, but when I use debounce it works.

import React, { useState, useRef } from "react";
import { throttleTime, debounceTime } from "rxjs/operators";
import { Subject } from "rxjs";

const subject = new Subject();

function Button() {
  const btn = useRef();
  const [clickCount, updateClick] = useState(0);
  const [debounceCount, updateDebounced] = useState(0);
  const [throttleCount, updateThrottled] = useState(0);
  const onClicked = e => {
    updateClick(parseInt(e.target.value, 10) + 1);
    subject.next(parseInt(e.target.value, 10) + 1);
  };
  subject.pipe(debounceTime(500)).subscribe(d => updateDebounced(d));
  subject.pipe(throttleTime(400)).subscribe(d => updateThrottled(d));
  return (
    <div className="button">
      <button value={clickCount} ref={btn} onClick={onClicked}>
        CLICK
      </button>
      <div>Actual clicks: {clickCount}</div>
      <div>Debounced clicks: {debounceCount}</div>
      <div>Throttle click: {throttleCount}</div>
    </div>
  );
}

the problem is each click clickCount and throttleCount increases at same time but debounceCount works as expected, it wait 500ms and updates.

working live demo

Wimal Weerawansa
  • 309
  • 2
  • 15
  • 33

1 Answers1

0

The component function Button() is called on every state change so you're making a new subscription on every state change. That's why it appears like it doesn't work.

Instead the subscription should go into useEffect():

useEffect(() => {
  subject.pipe(throttleTime(400)).subscribe(d => updateThrottled(d));
}, []);

Also see How to call loading function with React useEffect only once.

martin
  • 93,354
  • 25
  • 191
  • 226