Skip to content

Instantly share code, notes, and snippets.

@jdtibbs
Created January 16, 2017 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdtibbs/a118293b66265cca3fdd8c5863310f31 to your computer and use it in GitHub Desktop.
Save jdtibbs/a118293b66265cca3fdd8c5863310f31 to your computer and use it in GitHub Desktop.
Redux via RxJs & Ramda
<h3>See console for results</h3>

Redux via RxJs & Ramda

This implementation allows for multiple state objects in one RxJs observable.

A Pen by Jack on CodePen.

License.

console.clear()
// action : {pets: true, state: [{name:'spot',type:'dog'},{name:'nip',type:'cat'}]}
// action : {pet: true, state: {name:'spot',type:'dog'}}
// -> state : {pets: [...], pet:{...}}
const initialState = {};
const reducer = (state, action) => {
// update state based on action.
let _state = state;
// use R.cond to insure given state changes occur.
R.cond([
[R.prop('pet'), action => _state = R.merge(state, action.state)],
[R.prop('pets'), action => _state = R.merge(state, action.state)],
])(action)
// return state, changed or not.
return _state;
};
// const action = new Rx.BehaviorSubject(undefined); // late subscribers get last known state, but this does not work when there are multiple properties in state.
const action = new Rx.ReplaySubject(2); // with ReplaySubject, late subscribers get last known state, replay parameter must be >= number of properties in state.
const store = action.filter(R.compose(R.not, R.isNil)).startWith(initialState).scan(reducer); // subscribe to this.
// subscribe only to changes in state property 'pet'.
store.map(R.prop('pet')).filter(R.compose(R.not, R.isNil)).distinctUntilChanged().subscribe({
next: R.compose(console.log)
});
// subscribe only to changes in state property 'pets'.
store.map(R.prop('pets')).filter(R.compose(R.not, R.isNil)).distinctUntilChanged().subscribe({
next: R.compose(console.log)
});
// update state with data!
action.next({
pet: true,
state: {
pet: {
name: 'spot',
type: 'dog'
}
}
})
action.next({
pet: true,
state: {
pet: {
name: 'nip',
type: 'cat'
}
}
})
action.next({
pets: true,
state: {
pets: [{
name: 'spot',
type: 'dog'
}, {
name: 'nip',
type: 'cat'
}]
}
})
action.next({
pet: true,
state: {
pet: {
name: 'tweet',
type: 'bird'
}
}
})
action.next({
pets: true,
state: {
pets: [{
name: 'spot',
type: 'dog'
}, {
name: 'nip',
type: 'cat'
}, {
name: 'tweet',
type: 'bird'
}]
}
})
// because we are using a ReplaySubject(2) these late subscribers will get the last emitted state objects.
store.map(R.prop('pet')).filter(R.compose(R.not, R.isNil)).distinctUntilChanged().subscribe({
next: R.compose(console.log)
});
store.map(R.prop('pets')).filter(R.compose(R.not, R.isNil)).distinctUntilChanged().subscribe({
next: R.compose(console.log)
});
store.map(R.prop('pet')).filter(R.compose(R.not, R.isNil)).distinctUntilChanged().subscribe({
next: R.compose(console.log)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.0-beta.12/dist/global/Rx.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment