{"action":"closed","issue":{"url":"https://api.github.com/repos/rematch/rematch/issues/44","repository_url":"https://api.github.com/repos/rematch/rematch","labels_url":"https://api.github.com/repos/rematch/rematch/issues/44/labels{/name}","comments_url":"https://api.github.com/repos/rematch/rematch/issues/44/comments","events_url":"https://api.github.com/repos/rematch/rematch/issues/44/events","html_url":"https://github.com/rematch/rematch/issues/44","id":265911632,"number":44,"title":"'Recipes' for reducers, selectors, etc?","user":{"login":"blairbodnar","id":991976,"avatar_url":"https://avatars3.githubusercontent.com/u/991976?v=4","gravatar_id":"","url":"https://api.github.com/users/blairbodnar","html_url":"https://github.com/blairbodnar","followers_url":"https://api.github.com/users/blairbodnar/followers","following_url":"https://api.github.com/users/blairbodnar/following{/other_user}","gists_url":"https://api.github.com/users/blairbodnar/gists{/gist_id}","starred_url":"https://api.github.com/users/blairbodnar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blairbodnar/subscriptions","organizations_url":"https://api.github.com/users/blairbodnar/orgs","repos_url":"https://api.github.com/users/blairbodnar/repos","events_url":"https://api.github.com/users/blairbodnar/events{/privacy}","received_events_url":"https://api.github.com/users/blairbodnar/received_events","type":"User","site_admin":false},"labels":[{"id":707549556,"url":"https://api.github.com/repos/rematch/rematch/labels/question","name":"question","color":"cc317c","default":true}],"state":"closed","locked":false,"assignee":{"login":"ShMcK","id":4660659,"avatar_url":"https://avatars0.githubusercontent.com/u/4660659?v=4","gravatar_id":"","url":"https://api.github.com/users/ShMcK","html_url":"https://github.com/ShMcK","followers_url":"https://api.github.com/users/ShMcK/followers","following_url":"https://api.github.com/users/ShMcK/following{/other_user}","gists_url":"https://api.github.com/users/ShMcK/gists{/gist_id}","starred_url":"https://api.github.com/users/ShMcK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ShMcK/subscriptions","organizations_url":"https://api.github.com/users/ShMcK/orgs","repos_url":"https://api.github.com/users/ShMcK/repos","events_url":"https://api.github.com/users/ShMcK/events{/privacy}","received_events_url":"https://api.github.com/users/ShMcK/received_events","type":"User","site_admin":false},"assignees":[{"login":"ShMcK","id":4660659,"avatar_url":"https://avatars0.githubusercontent.com/u/4660659?v=4","gravatar_id":"","url":"https://api.github.com/users/ShMcK","html_url":"https://github.com/ShMcK","followers_url":"https://api.github.com/users/ShMcK/followers","following_url":"https://api.github.com/users/ShMcK/following{/other_user}","gists_url":"https://api.github.com/users/ShMcK/gists{/gist_id}","starred_url":"https://api.github.com/users/ShMcK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ShMcK/subscriptions","organizations_url":"https://api.github.com/users/ShMcK/orgs","repos_url":"https://api.github.com/users/ShMcK/repos","events_url":"https://api.github.com/users/ShMcK/events{/privacy}","received_events_url":"https://api.github.com/users/ShMcK/received_events","type":"User","site_admin":false},{"login":"scottclayton","id":10013159,"avatar_url":"https://avatars1.githubusercontent.com/u/10013159?v=4","gravatar_id":"","url":"https://api.github.com/users/scottclayton","html_url":"https://github.com/scottclayton","followers_url":"https://api.github.com/users/scottclayton/followers","following_url":"https://api.github.com/users/scottclayton/following{/other_user}","gists_url":"https://api.github.com/users/scottclayton/gists{/gist_id}","starred_url":"https://api.github.com/users/scottclayton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottclayton/subscriptions","organizations_url":"https://api.github.com/users/scottclayton/orgs","repos_url":"https://api.github.com/users/scottclayton/repos","events_url":"https://api.github.com/users/scottclayton/events{/privacy}","received_events_url":"https://api.github.com/users/scottclayton/received_events","type":"User","site_admin":false}],"milestone":null,"comments":5,"created_at":"2017-10-16T20:48:55Z","updated_at":"2017-10-17T19:59:02Z","closed_at":"2017-10-17T19:59:01Z","author_association":"COLLABORATOR","body":"@ShMcK @scottclayton \r\n\r\nI'm just brainstorming... Not sure if this is something that we want to rematch to help with or not. But I'm wondering if it would be nice to have some pre-made 'recipes' for common state designs? Not sure if 'recipes' is the right word here... hmm.\r\n\r\n@ShMcK We briefly chatted about this the other day. I think I said something along the lines of \"I use a lot of similar reducers and selectors, I want to reuse them!\". And you said something along the lines of \"What if we use object spread?\"\r\n\r\nSo, here's a brain-dump:\r\n\r\nI find that as I develop my apps, I tend to come up with a state structure for common things. For example, I end up using the same state structure when dealing with a collection...\r\n\r\nSomeone:  \"Make me a todo-list\"\r\nMe: \"Ok\"\r\nMy brain:\r\n#### ./models/todos.js\r\n```js\r\nmodel({\r\n  name: 'todos',\r\n  // I might have state like this. I kinda like this pattern of `state.id.item`\r\n  state: {\r\n    '2fc9acde': {\r\n      text: 'release rematch to the wild',\r\n      done: false\r\n    },\r\n    'fb6bb0e4': {\r\n      text: 'drink coffee',\r\n      done: true\r\n    }  \r\n  },\r\n  // with reducers like this...\r\n  reducers: {\r\n    addItem: (state, payload) => { ... },\r\n    removeItem: (state, payload) => { ... },\r\n    updateItem: (state, payload) => { ... },\r\n    clearList: (state, payload) => { ... },\r\n    // etc.\r\n  }\r\n  // and selectors like this...\r\n  selectors: {\r\n    getItem: (state, payload) => { ... },\r\n    findById: (state, payload) => { ... },\r\n    getIds: (state) => { ... },\r\n    getItemProperty: (state, payload) => { ... },\r\n    // etc.\r\n  }\r\n})\r\n```\r\nLater on...\r\n\r\nSomeone: \"Make me a shopping cart\"\r\nMe: \"Ok\"\r\nMy brain: \"Hey, I liked the way I dealt with the collection in my todos model. I think I'll use the same design for this part of my shopping cart...\"\r\n\r\nSo, maybe I move my reducers and selectors somewhere so they can be reused...\r\n#### ./recipes/collection.js\r\n```js\r\nexport const reducers = {\r\n  addItem: (state, payload) => { ... },\r\n  removeItem: (state, payload) => { ... },\r\n  updateItem: (state, payload) => { ... },\r\n  clearList: (state, payload) => { ... },\r\n  // etc.\r\n}\r\n\r\nexport const selectors = {\r\n  getItem: (state, payload) => { ... },\r\n  findById: (state, payload) => { ... },\r\n  getIds: (state) => { ... },\r\n  getItemProperty: (state, payload) => { ... },\r\n  // etc.\r\n}\r\n```\r\nAnd then use them in models that deal with collections with the same state structure.\r\n#### ./models/todos.js\r\n```js\r\nimport { reducers, selectors } from './recipes/collection'\r\nmodel({\r\n  name: 'todos',\r\n  state: {\r\n    '2fc9acde': {\r\n      text: 'release rematch to the wild',\r\n      done: false\r\n    },\r\n  },\r\n  reducers: { ...reducers },\r\n  selectors: { ...selectors },\r\n})\r\n```\r\n#### ./models/shoppingCart.js\r\n```js\r\nimport { reducers, selectors } from './recipes/collection'\r\nmodel({\r\n  name: 'shoppingCart',\r\n  state: {\r\n    '9bd1e596': {\r\n      item: 'reese peanut butter cups',\r\n      quantity: 99\r\n    },\r\n  },\r\n  reducers: {\r\n    ...reducers,\r\n    anotherReducer:  (state, payload) => { ... },\r\n    // etc.\r\n  },\r\n  selectors: {\r\n    ...selectors,\r\n    anotherSelector:  (state, payload) => { ... },\r\n    // etc.\r\n  },\r\n})\r\n```\r\n\r\n\r\n"}}
{"actor":{"display_login":"ShMcK"}}