Reputation: 7173
I'm building a carousel component in React and I want the consumable functions (things like advanceSlide, rewindSlide, etc) to return RxJS Observable
s they easily can be chained, merged, whatever with other observables.
As it stands now, my advance
function looks like:
advance = (toIndex = this.state.focusedIndex + 1, animated = true) => {
const destinationIndex = Math.max(0, Math.min(toIndex, this.props.children.length));
const itemPosition = this._positions[destinationIndex];
const domNode = $(ReactDOM.findDOMNode(this.refs.track));
const animate = Rx.Observable.fromCallback(domNode.animate.bind(domNode));
this.setState({ focusedIndex: destinationIndex });
return animate({
top: '-' + itemPosition.top + 'px'
}, animated ? this.props.speed : 0);
};
Ideally I want to call this function like:
this.refs.carousel.advance().delay().repeat(); //achieve infinite carousel
However, and quite obviously, the observable returned from advance
uses the same calculations upon repeat (since the function is invoked once with .advance()
and just the observable is repeated.
What I need is a way to return an observable that runs the animation calculations again and then returns a new observable every time it's repeated.
To better illustrate what I want to achieve:
carousel.advance().repeat(1).subscribe();
On the first invocation, the position and whatnot are calculated, the animation observable is returned, it runs, and everything animates correctly.
On the second invocation, the signal is repeated with the same values so to the user, it appears as though nothing happens because the advance
function hasn't been reinvoked.
How do I achieve that functionality using RxJS? I've been looking into using Rx.Observable.spawn
but it doesn't seem to be what I need.
Upvotes: 1
Views: 507
Reputation: 18665
The advance
function is not reinvoked indeed but the observable that it outputs is resubscribed to.
Also note that you should use repeat(2)
if you want to repeat once (I know it sounds strange).
If you want to repeat advance
why don't you put it inside the observable chain? For example :
var Xms = 1000; // 1s
advanceRepeated = (context) => {
return Rx.Observable.just(context)
.flatMap ((context) => {
return context.refs.carousel.advance().delay(Xms);
})
.repeat(2)
}
This is untested, so let me know if it indeed worked and please keep an eye for possible syntax errors.
Upvotes: 2