Skip to content

Instantly share code, notes, and snippets.

@amsterdamharu
Last active March 17, 2021 19:14
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 amsterdamharu/1e21537a4b0a4767975e8eea3665b91c to your computer and use it in GitHub Desktop.
Save amsterdamharu/1e21537a4b0a4767975e8eea3665b91c to your computer and use it in GitHub Desktop.
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