RxJS and React multiple clicked elements to form single data array
Make your filter items an Observable streams of click events using Rx.Observable.fromevent
(see https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/events.md#converting-a-dom-event-to-a-rxjs-observable-sequence) - it understands a multi-element selector for the click handling.
You want to keep receiving click events until a debounce has been hit (user has enabled/disabled all filters she wants to use). You can use the Buffer
operator for this with a closingSelector
which needs to emit a value when to close the buffer and emit the buffered values.
But leaves the issue how to know the current actual state.
UPDATE
It seems to be far easier to use the .scan
operator to create your filterState array and debounce these.
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);
Actually, your problem is about RxJS, not React itself. So it is easy. Suppose you have two function:
const removeTag = tagName => tags => { const index = tags.indexOf(index) if (index !== -1) return tags else return tags.splice(index, 1, 0) }const addTag = tagName => tags => { const index = tags.indexOf(index) if (index !== -1) return tags.push(tagName) else return tags }
Then you can either using scan
:
const modifyTags$ = new Subject()modifyTags$.pipe( scan((tags, action) => action(tags), [])).subscribe(tags => sendRequest(tags))modifyTags$.next(addTag('a'))modifyTags$.next(addTag('b'))modifyTags$.next(removeTag('a'))
Or having a separate object for tags
:
const tags$ = new BehaviorSubject([])const modifyTags$ = new Subject()tags$.pipe( switchMap( tags => modifyTags$.pipe( map(action => action(tags)) ) )).subscribe(tags$)tags$.subscribe(tags => sendRequest(tags))