Dustin McCraw
import { createSelector } from 'reselect'
const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent
const subtotalSelector = createSelector(
shopItemsSelector,
items => items.reduce((acc, item) => acc + item.value, 0)
)
const taxSelector = createSelector(
subtotalSelector,
taxPercentSelector,
(subtotal, taxPercent) => subtotal * (taxPercent / 100)
)
export const totalSelector = createSelector(
subtotalSelector,
taxSelector,
(subtotal, tax) => ({ total: subtotal + tax })
)
let exampleState = {
shop: {
taxPercent: 8,
items: [
{ name: 'apple', value: 1.20 },
{ name: 'orange', value: 0.95 },
]
}
}
console.log(subtotalSelector(exampleState)) // 2.15
console.log(taxSelector(exampleState)) // 0.172
console.log(totalSelector(exampleState)) // { total: 2.322 }
{
divisions: {
1: { id: 1, name: "National Football League", rootId: 1 },
3: { id: 3, name: "American Football Conference", rootId: 1 },
5: { id: 5, name: "National Football Conference", rootId: 1 }
},
teams: {
101: { id: 101, name: "New England Patriots", divisionId: 2 },
102: { id: 102, name: "Denver Broncos", divisionId: 2 },
203: { id: 203, name: "San Francisco 49ers", divisionId: 3 },
204: { id: 204, name: "Philadelphia Eagles", divisionId: 3 }
},
members: {
17: { id: 17, firstName: "Roger", lastName: "Goodell", divisionId: 1, teamId: nil },
19: { id: 19, firstName: "Nick", lastName: "Foles", divisionId: 5, teamId: 204 },
21: { id: 21, firstName: "Jay", lastName: "Ajayi", divisionId: 5, teamId: 204 },
23: { id: 23, firstName: "Jimmy", lastName: "Garoppolo", divisionId: 5, teamId: 203 },
25: { id: 25, firstName: "Matt", lastName: "Breida", divisionId: 5, teamId: 203 },
27: { id: 27, firstName: "Tom", lastName: "Brady", divisionId: 3, teamId: 101 },
29: { id: 29, firstName: "Brandon", lastName: "Bolden", divisionId: 3, teamId: 101 },
31: { id: 31, firstName: "Paxton", lastName: "Lynch", divisionId: 3, teamId: 102 },
33: { id: 33, firstName: "C.J.", lastName: "Anderson", divisionId: 3, teamId: 102 }
}
}
const selectDivisions = state => state.divisions
const selectTeams = state => state.teams
const selectMembers = state => state.members
const selectRawMembers = state => state.members
const selectMembers = createSelector(
selectRawMembers,
(rawMembers) => {
let members = {}
Object.values(rawMembers).forEach((member) => {
members[member.id] = {
...member,
fullName: `${member.firstName} ${member.lastName}`
}
})
return members
}
)
members: {
17: { id: 17, firstName: "Roger", lastName: "Goodell", ..., fullName: "Roger Goodell" },
19: { id: 19, firstName: "Nick", lastName: "Foles", ..., fullName: "Nick Foles" },
21: { id: 21, firstName: "Jay", lastName: "Ajayi", ..., fullName: "Jay Ajayi" },
23: { id: 23, firstName: "Jimmy", lastName: "Garoppolo", ..., fullName: "Jimmy Garoppolo" },
25: { id: 25, firstName: "Matt", lastName: "Breida", ..., fullName: "Matt Breida" }
27: { id: 27, firstName: "Tom", lastName: "Brady", ..., fullName: "Tom Brady" },
29: { id: 29, firstName: "Brandon", lastName: "Bolden", ..., fullName: "Brandon Bolden" },
31: { id: 31, firstName: "Paxton", lastName: "Lynch", ..., fullName: "Paxton Lynch" },
33: { id: 33, firstName: "C.J.", lastName: "Anderson", ..., fullName: "C.J. Anderson" }
}
const selectRawMembers = state => state.members
const selectMembers = createSelector(
selectRawMembers, selectTeams, selectDivisions,
(rawMembers, teams, divisions) => {
let members = {}
Object.values(rawMembers).forEach((member) => {
members[member.id] = {
...member,
fullName: `${member.firstName} ${member.lastName}`,
teamName: teams[member.teamId] ? teams[member.teamId].name : '',
divisionName:
divisions[member.divisionId] ? divisions[member.divisionId].name : '',
}
})
return members
}
)
members: {
17: { id: 17, ..., teamName: "", divisionName: "National Football League" },
19: { id: 19, ..., teamName: "Philadelphia Eagles", divisionName: "American Football Conference" },
21: { id: 21, ..., teamName: "Philadelphia Eagles", divisionName: "American Football Conference" },
23: { id: 23, ..., teamName: "San Francisco 49ers", divisionName: "American Football Conference" },
25: { id: 25, ..., teamName: "San Francisco 49ers", divisionName: "American Football Conference" },
27: { id: 27, ..., teamName: "New England Patriots", divisionName: "National Football Conference" },
29: { id: 29, ..., teamName: "New England Patriots", divisionName: "National Football Conference" },
31: { id: 31, ..., teamName: "Philadelphia Eagles", divisionName: "National Football Conference" },
33: { id: 33, ..., teamName: "Philadelphia Eagles", divisionName: "National Football Conference" }
}
const selectAndSortBy = (collection, by) => {
const sortedBy = {}
Object.values(collection, (item) => {
if (item[by] !== undefined) {
if (!sortedBy[item[by]]) {
sortedBy[item[by]] = []
}
sortedBy[item[by]].push(item)
}
})
return sortedBy
}
const selectMembersByDivision = createSelector(
selectMembers,
members => selectAndSortBy(members, 'divisionId')
)
selectMembersByDivision(state)
{
1: [
{ id: 17, firstName: "Roger", lastName: "Goodell", divisionId: 1, teamId: nil }
],
3: [
{ id: 27, firstName: "Tom", lastName: "Brady", divisionId: 3, teamId: 101 },
{ id: 29, firstName: "Brandon", lastName: "Bolden", divisionId: 3, teamId: 101 },
{ id: 31, firstName: "Paxton", lastName: "Lynch", divisionId: 3, teamId: 102 },
{ id: 33, firstName: "C.J.", lastName: "Anderson", divisionId: 3, teamId: 102 }
],
5: [
{ id: 19, firstName: "Nick", lastName: "Foles", divisionId: 5, teamId: 204 },
{ id: 21, firstName: "Jay", lastName: "Ajayi", divisionId: 5, teamId: 204 },
{ id: 23, firstName: "Jimmy", lastName: "Garoppolo", divisionId: 5, teamId: 203 },
{ id: 25, firstName: "Matt", lastName: "Breida", divisionId: 5, teamId: 203 },
]
}
const selectMembersByDivisionId = state => divisionId => (
selectMembersByDivision(state)[divisionId] || []
)
// thoughts about providing a default value?
// pass a function that already selects the members
const mapStateToProps = (state, ownProps) => (
return {
members: selectMembersByDivisionId(state)(ownProps.divisionId)
}
)
this.props.members
// or pass a function that allows the component to select the members
const mapStateToProps = (state, ownProps) => (
return {
membersByDivisionId: selectMembersByDivisionId(state)
}
)
this.props.membersByDivisionId(divisionId)
selectAndSortContactEmailAddressesByMemberId
selectAndSortBroadcastEmailsByMemberId
selectAndSortContactsByMemberId
selectAndSortInvoicesByBatchInvoiceId
The list goes on and on.
Thoughts on ways to most efficiently use these patterns or other patterns that we should use?