Last active
March 17, 2021 19:14
-
-
Save amsterdamharu/1e21537a4b0a4767975e8eea3665b91c to your computer and use it in GitHub Desktop.
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 state = { | |
people: { | |
1: { id: 1, name: 'one' }, | |
2: { id: 2, name: 'two' }, | |
3: { id: 3, name: 'three' }, | |
}, | |
likes: { | |
1: [2, 3], | |
2: [1], | |
3: [1], | |
}, | |
}; | |
const selectPeople = state => state.people; | |
const selectLikes = state => state.likes; | |
const createSelectPerson = id => | |
createSelector( | |
selectPeople, | |
data => | |
console.log('returning person for', id) || data[id] | |
); | |
const createSelectPersonLikes = id => | |
createSelector(selectLikes, likes => likes[id]); | |
const createSelectLikedBy = id => { | |
const memoizedLikedBy = defaultMemoize((...args) => args); | |
const selectPeopleLikedBy = state => | |
memoizedLikedBy( | |
//memoize it (if id's didnt change then don't re create) | |
...Object.entries(selectLikes(state)) | |
.filter(([, likes]) => likes.includes(id)) | |
.map(([key]) => Number(key)) | |
); | |
return createSelector( | |
selectPeople, //all people | |
selectPeopleLikedBy, | |
(people, likedByIds) => likedByIds.map(id => people[id]) | |
); | |
}; | |
//when creating a list of people then each person needs it's own | |
// selector in order for memoization to work | |
const createSelectPersonForComponent = id => | |
createSelector( | |
selectPeople, | |
createSelectPerson(id), | |
createSelectPersonLikes(id), | |
createSelectLikedBy(id), | |
(data, person, likes, likedBy) => { | |
console.log('(re) creating person with likes,', id); | |
return { | |
...person, | |
likes: likes.map(friendId => data[friendId]), | |
likedBy, | |
}; | |
} | |
); | |
const PersonComponent = ({ id }) => { | |
const selectPerson = createSelectPersonForComponent(id); | |
return { | |
render: state => { | |
const personWithLikes = selectPerson(state); | |
return `${ | |
personWithLikes.name | |
}, likes: ${personWithLikes.likes | |
.map(f => f.name) | |
.join( | |
',' | |
)}, liked by: ${personWithLikes.likedBy | |
.map(f => f.name) | |
.join(',')}`; | |
}, | |
}; | |
}; | |
const PersonList = Object.values(state.people).map( | |
PersonComponent | |
); | |
console.log( | |
PersonList.map(p => p.render(state)).join('\n') | |
); | |
const newState = { | |
...state, | |
likes: { | |
...state.likes, | |
1: state.likes[1].filter(f => f !== 2), | |
}, | |
}; | |
console.log( | |
PersonList.map(p => p.render(newState)).join('\n') | |
); | |
//Same code without memoization: | |
const state = { | |
people: { | |
1: { id: 1, name: 'one' }, | |
2: { id: 2, name: 'two' }, | |
3: { id: 3, name: 'three' }, | |
}, | |
likes: { | |
1: [2, 3], | |
2: [1], | |
3: [1], | |
}, | |
}; | |
const selectPeople = state => state.people; | |
const selectLikes = state => state.likes; | |
const selectPerson = createSelector( | |
selectPeople, | |
(_, id) => id, | |
(data, id) => | |
console.log('returning person for', id) || data[id] | |
); | |
const selectPersonLikes = createSelector( | |
selectPeople, | |
selectLikes, | |
(_, id) => id, | |
(people, likes, id) => likes[id].map(id => people[id]) | |
); | |
const selectLikedBy = createSelector( | |
selectPeople, | |
selectLikes, | |
(_, id) => id, | |
(people, likes, id) => | |
Object.entries(likes) | |
.filter(([, likes]) => likes.includes(id)) | |
.map(([key]) => people[key]) | |
); | |
const selectPersonForComponent = createSelector( | |
selectPerson, | |
selectPersonLikes, | |
selectLikedBy, | |
(_, id) => id, | |
(person, likes, likedBy, id) => { | |
console.log('(re) creating person with likes,', id); | |
return { | |
...person, | |
likes, | |
likedBy, | |
}; | |
} | |
); | |
const PersonComponent = ({ id }) => { | |
return { | |
render: state => { | |
const person = selectPersonForComponent(state, id); | |
return `${person.name}, likes: ${person.likes | |
.map(f => f.name) | |
.join(',')}, liked by: ${person.likedBy | |
.map(f => f.name) | |
.join(',')}`; | |
}, | |
}; | |
}; | |
const PersonList = Object.values(state.people).map( | |
PersonComponent | |
); | |
console.log( | |
PersonList.map(p => p.render(state)).join('\n') | |
); | |
const newState = { | |
...state, | |
likes: { | |
...state.likes, | |
1: state.likes[1].filter(f => f !== 2), | |
}, | |
}; | |
console.log( | |
PersonList.map(p => p.render(newState)).join('\n') | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment