Last active
August 23, 2017 23:44
-
-
Save scott-coates/d53c9de94147eae5f7c6 to your computer and use it in GitHub Desktop.
Imperative vs FRP code. 'Subscribe' to a Redux Store, only receiving events when a specific piece of state is changed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const teamStream = storeObserver.observeStateStream(store, state => state.team.requestedTeam.id); | |
teamStream.onValue(requestedTeamId => { | |
// clean up old connection (this will happen if we look at different teams) | |
if (this.teamRef) this.teamRef.off('value', this.teamCallback); | |
this.teamRef = rootRef.child(`teams/${requestedTeamId}`); | |
this.teamCallback = this.teamRef.on('value', snapshot => { | |
try { | |
const team = firebaseService.prepareObject(snapshot); | |
if (team.executionDate) team.executionDate = ymdFormat(dateFromTimestamp(team.executionDate)); | |
store.dispatch(teamActions.teamReceived(team)); | |
} catch (error) { | |
throw new Error(`Error providing team data from firebase: Inner exception: ${error.stack}`); | |
} | |
}, error => { | |
throw new Error(`Error retrieving team data from firebase: Inner exception: ${error.stack}`); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
store.subscribe(_ => { | |
const state = store.getState(); | |
// we need to do this the very first time (requestedTeamId will be null). | |
const requestedTeamId = state.team.requestedTeam.id; | |
if (requestedTeamId) { | |
if (this.currentRequestedTeam.id !== requestedTeamId) { | |
// clean up old connection (this will happen if we look at different team) | |
if (this.teamRef) this.teamRef.off('value', this.teamCallback); | |
this.currentRequestedTeam.id = requestedTeamId; | |
this.teamRef = rootRef.child(`teams/${this.currentRequestedTeam.id}`); | |
this.teamCallback = this.teamRef.on('value', snapshot => { | |
try { | |
const team = FirebaseService.prepareObject(snapshot); | |
store.dispatch(teamActions.teamReceived(team)); | |
} catch (error) { | |
throw new Error(`Error providing team data from firebase: Inner exception: ${error.stack}`); | |
} | |
}, error => { | |
throw new Error(`Error retrieving team data from firebase: Inner exception: ${error.stack}`); | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bacon from 'baconjs'; | |
import equals from 'deep-equal'; | |
export default { | |
observeStateStream(store, mapFunc){ | |
const storeBinderFunc = sink => { | |
store.subscribe(_=>sink(store.getState())); | |
}; | |
const stream = bacon | |
.fromBinder(storeBinderFunc) | |
// get the initial state now so we have something to compare against on the next event. | |
.startWith(store.getState()) | |
.map(mapFunc) | |
.skipDuplicates(equals) | |
// do not log first time | |
.skip(1); | |
return stream; | |
} | |
}; | |
// const TeamStream = storeObserver.observeStateStream(store, state=> state.team.requestedTeam.id); | |
// teamStream.onValue(console.log.bind(console, "New team ID is")); | |
// Console Output: New team ID is bF8fLMXn |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This snippet is inspired from http://stackoverflow.com/questions/31268740/firing-redux-actions-in-response-to-route-transitions-in-react-router/31312139#31312139.
Note:
store.subscribe
is invoked anytime its internal state changes.before.js
before.js
shows an imperative approach. We're keeping track ofstore
's state (particularlyrequestedTeamId
) with a temp variablecurrentRequestedTeam
. We use this temp variable to detect whenrequestedTeamId
changes. It uses a bunch of conditionals and temp variables - I've found that these are often scenarios in which FRP can come in handy.after.js
This approach allows us to specify which piece of state we care about and only when it changes will an event be fired.