{"action":"created","issue":{"url":"https://api.github.com/repos/staltz/cycle-onionify/issues/28","repository_url":"https://api.github.com/repos/staltz/cycle-onionify","labels_url":"https://api.github.com/repos/staltz/cycle-onionify/issues/28/labels{/name}","comments_url":"https://api.github.com/repos/staltz/cycle-onionify/issues/28/comments","events_url":"https://api.github.com/repos/staltz/cycle-onionify/issues/28/events","html_url":"https://github.com/staltz/cycle-onionify/issues/28","id":225517252,"number":28,"title":"Collection API and pickCombine/pickMerge","user":{"login":"staltz","id":90512,"avatar_url":"https://avatars0.githubusercontent.com/u/90512?v=3","gravatar_id":"","url":"https://api.github.com/users/staltz","html_url":"https://github.com/staltz","followers_url":"https://api.github.com/users/staltz/followers","following_url":"https://api.github.com/users/staltz/following{/other_user}","gists_url":"https://api.github.com/users/staltz/gists{/gist_id}","starred_url":"https://api.github.com/users/staltz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/staltz/subscriptions","organizations_url":"https://api.github.com/users/staltz/orgs","repos_url":"https://api.github.com/users/staltz/repos","events_url":"https://api.github.com/users/staltz/events{/privacy}","received_events_url":"https://api.github.com/users/staltz/received_events","type":"User","site_admin":false},"labels":[{"id":441810852,"url":"https://api.github.com/repos/staltz/cycle-onionify/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":36,"created_at":"2017-05-01T20:22:08Z","updated_at":"2017-05-23T20:48:56Z","closed_at":null,"body":"I pushed to the [collection](https://github.com/staltz/cycle-onionify/tree/collection) branch an experimental feature where we borrow an API from [Cycle Collection](https://github.com/cyclejs/collection/) and improve performance under the hood.\r\n\r\nThe gist is:\r\n\r\n**Create many instances of a component using collection**\r\n\r\n```js\r\nfunction MyList(sources) {\r\n  // ...\r\n\r\n  // Expects sources.onion.state$ to be a Stream<Array<ItemState>>\r\n  const instances$ = collection(Item, sources, itemState => itemState.key)\r\n  // the above is the same as\r\n  //const instances$ = collection(Item, sources)\r\n```\r\n\r\n**pickCombine('DOM') is pick('DOM') + mix(xs.combine)**\r\n\r\n```js\r\nconst childrenvnodes$ = instances$.compose(pickCombine('DOM'))\r\n```\r\n\r\n**pickMerge('onion') is pick('onion') + mix(xs.merge)**\r\n\r\n```js\r\nconst childrenreducer$ = instances$.compose(pickMerge('onion'))\r\n```\r\n\r\n- - -\r\n\r\n*Note: this is an experiment. That's why it's in a branch.*\r\n\r\nThe motivation for this was to make onionify faster for large amounts of child components from an array. The main solution for this was `pickCombine` and the internal data structure of \"instances\" which `collection` builds. `pickCombine` is a fusion of pick+mix to avoid a combine, a flatten, and a map, and does all of these together and takes shortcuts to avoid recalculating things in vain. `collection` was sort a necessity from two perspectives: (1) easier than creating and isolating item components by hand, (2) with this performance improvement it would have become even harder to do it by hand.\r\n\r\nCheck the [advanced](https://github.com/staltz/cycle-onionify/tree/e8e78faa504a62336a5c4b0ef0696dcbe5bd1c7e/examples/advanced) example.\r\n\r\nWe're looking for feedback in order to find the **most suitable API** that feels quick to learn for the average programmer, while solving the problems below too. In other words, the challenge here is API design for developer experience. The challenge is not \"how\" to solve the technical problem.\r\n\r\nOpen problems/questions:\r\n\r\n- [x] *Solved thanks to a PR by @abaco.* A child component may get double updates since it is onionified as well as the parent is. When the child component sends out a reducer to the onion sink, it will update its onion source state, but also the parent onion source state. We need to find a way to make the child avoid the second update since its redundant.\r\n- [x] Update or replace the test \"should work with an isolated list child with a default reducer\"\r\n- [x] How do we allow lenses on individual items, like we can do e.g. in example `mixed`?\r\n- [x] `collection()` does a lot under the hood (creates the instances data structure, calls onionify, picks the key from each item state, creates item state lenses, onionifies each child component, etc). Do we want to have heavy configuration with many arguments, or do we want to break that down into other helper functions? And how?\r\n- [ ] This change expects item state to have a unique `key`. Do we still want to allow keyless items in a list? \r\n- [ ] How to avoid fragility to object equality issues? (read the thread)\r\n- [ ] How to keep the feature where we can pass a channel name instead of \"onion\"\r\n"},"comment":{"url":"https://api.github.com/repos/staltz/cycle-onionify/issues/comments/303527618","html_url":"https://github.com/staltz/cycle-onionify/issues/28#issuecomment-303527618","issue_url":"https://api.github.com/repos/staltz/cycle-onionify/issues/28","id":303527618,"user":{"login":"abaco","id":1866728,"avatar_url":"https://avatars1.githubusercontent.com/u/1866728?v=3","gravatar_id":"","url":"https://api.github.com/users/abaco","html_url":"https://github.com/abaco","followers_url":"https://api.github.com/users/abaco/followers","following_url":"https://api.github.com/users/abaco/following{/other_user}","gists_url":"https://api.github.com/users/abaco/gists{/gist_id}","starred_url":"https://api.github.com/users/abaco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abaco/subscriptions","organizations_url":"https://api.github.com/users/abaco/orgs","repos_url":"https://api.github.com/users/abaco/repos","events_url":"https://api.github.com/users/abaco/events{/privacy}","received_events_url":"https://api.github.com/users/abaco/received_events","type":"User","site_admin":false},"created_at":"2017-05-23T20:48:56Z","updated_at":"2017-05-23T20:48:56Z","body":"> \"We must have a way of creating a collection from list inside state = {a, b, c, list}, without introducing a List component\"\r\n\r\nExactly, that's how I understand @jvanbruegge's need."}}
{"actor":{"display_login":"abaco"}}