RxJS has a nifty function, fromCallback that takes a function whose last parameter is a callback and returns an Observable
. And I want to combine that with React's setState
function so that I can do something analogous to:
const setState = Rx.Observable.fromCallback(this.setState);
setState({ myState: 'Hi there!' }).concat(....)
so that any operations chained to setState are guaranteed to happen after the state has been set and, most importantly, that setState
isn't invoked until there's an active subscriber.
What I noticed though is that even without a subscribe, setState
is being called right as it's defined and setting the state of my component. So if I have:
networkSignal.flatMap((x) => {
return setState({ myState: 'test' });
});
the function setState
is immediately invoked but the observer it producers won't send a next until there's a subscriber. What I want is for the function to only invoke when there's a subscriber.
Looking into the source you can see that RxJS returns a function that when executed, creates an observable but immediately invokes the function - the callback argument.
defer
andfromCallback
as was suggested in the answer, I do something likeRx.Observable.defer(() => setState))
which first sets a function to defer, and calls the observable function created earlier fromfromCallback
– barndogsetState
callback, this is really an observable version of doing that. Also, because of the nature offromCallback
, the returned function is executed immediately, the value just doesn't propagate until there's a subscriber. In the case ofsetState
, as soon as it's called it sets the state, regardless if there's a subscriber. – barndogsetState({ someState: 'hi' }).concat(Rx.Observable.just(42))
. I, the reader of this code would assume that when subscription began thatsetState
would be called and so on and so forth. However, it's called on the observables creation, not on it's subscription. So if you create an observable and store it away for later use, the state gets set, not as part of the observer chain. – barndogsetState
or really anything else into an observable so that you delay the function execution until subscription, indefer
make sure you return an observable i.e.Rx.Observable.defer(() => { return setState({ state: 1 }); }
. With es6 it's implicit in one line functions but I just ran into an issue with not returning inside the defer. Threw me for a loop. – barndog