The store API is meant to be extensible. This is why it needs to be as orthogonal as possible. The methods shouldn't duplicate functionality because otherwise creating extensions to it like Redux DevTools becomes harder. If extensions want to do something to the state before passing it to the consumer, they'll now have to do it in two different places (three if we add two parameters!) which is error prone.
The solution is simple: don't use subscribe directly! It's a low level API. If you want it to behave as an Observable, write a function that turns it into an observable! It isn't hard to do:
function toObservable(store) {
return {
subscribe({ onNext }) {
let dispose = store.subscribe(() => onNext(store.getState()));
onNext(store.getState());
return { dispose };
}
}
}
If you don't want to use RX and prefer a callback with previous and next value, again, easy to do. You can even do selecting as part of it:
function observeStore(store, select, onChange) {
let currentState;
function handleChange() {
let nextState = select(store.getState());
if (nextState !== currentState) {
currentState = nextState;
onChange(currentState);
}
}
let unsubscribe = store.subscribe(handleChange);
handleChange();
return unsubscribe;
}
We can provide either as a utility inside Redux, if we can converge on the API people want.
What we can't do is make Store interface less low-level and duplicating functionality between methods, because then building extensions on top of it becomes way harder.
By Dan Abramov