Last active
November 20, 2017 21:45
-
-
Save sikanhe/9b940ce866d78354bba3 to your computer and use it in GitHub Desktop.
Most efficient way to store domain state in Redux (Indexed Key-Value Store)
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
//After working on the backend for a while, I started to continue working on my front end, | |
//I revisited my redux “cache” store and I made this improvement that made my life a lot easier. | |
//In my project for example, some collections i need to get the document by id, some by slug, some by username, and etc. | |
//If I need to account for those cases I had to make new action creators/types, for different entities. | |
//This is very frustrating as it makes the code less dry and leads to more boilerplate. | |
//Then what I realized was, I can just pass a “index” option for my insert action creators!(which defaults to “id") | |
//Actions | |
const actions = { | |
INSERT_ONE: 'INSERT_ONE', | |
INSERT_MANY: 'INSERT_MANY' | |
} | |
//Action Creators | |
export function insert(collection, payload, { index } = { index: 'id'}) { | |
if(Array.isArray(doc)) { | |
return { | |
type: actions.INSERT_MANY, | |
collection, | |
docs: payload, | |
index | |
} | |
} else { | |
return { | |
type: actions.INSERT_ONE, | |
collection, | |
doc: payload, | |
index | |
} | |
} | |
} | |
//Reducer | |
const defaultState = { | |
users: {}, | |
posts: {} | |
} | |
export default function cache(state = defaultState, action) { | |
const { collection, index, doc } = action; | |
switch(action.type) { | |
default: | |
return state; | |
case actions.INSERT_ONE: | |
return { | |
...state, | |
[collection]: { | |
...state[collection], | |
[doc[index]]: doc | |
} | |
}; | |
case actions.INSERT_MANY: | |
const newDocs = {}; | |
docs.forEach(doc => { | |
newDocs[ doc[index] ] = doc | |
}); | |
return { | |
...state, | |
[action.collection]: { | |
...state[action.collection], | |
...newDocs | |
} | |
} | |
} | |
} | |
//How to insert | |
this.props.insert('users', user, {index: 'username'}); | |
this.props.insert('posts', post, {index: 'slug'}); | |
this.props.insert('posts', post); // index by "id" | |
// Now I can easily get document by the property I usually use for that type | |
const user = cache.users["some_username"]; //get using username | |
const post = cache.posts["some-title-slug"]; //get using slug | |
const post = cache.posts["234j2kl3j42h3j4l"] //get using id | |
//Joins in my components | |
const post = cache.posts["some-slug"]; | |
post.user = cache.users[post.user_id]; | |
//Easy peazy! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment