{"action":"created","issue":{"url":"https://api.github.com/repos/dekujs/deku/issues/337","labels_url":"https://api.github.com/repos/dekujs/deku/issues/337/labels{/name}","comments_url":"https://api.github.com/repos/dekujs/deku/issues/337/comments","events_url":"https://api.github.com/repos/dekujs/deku/issues/337/events","html_url":"https://github.com/dekujs/deku/issues/337","id":124344906,"number":337,"title":"[Meta] v2 API thoughts","user":{"login":"rstacruz","id":74385,"avatar_url":"https://avatars.githubusercontent.com/u/74385?v=3","gravatar_id":"","url":"https://api.github.com/users/rstacruz","html_url":"https://github.com/rstacruz","followers_url":"https://api.github.com/users/rstacruz/followers","following_url":"https://api.github.com/users/rstacruz/following{/other_user}","gists_url":"https://api.github.com/users/rstacruz/gists{/gist_id}","starred_url":"https://api.github.com/users/rstacruz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rstacruz/subscriptions","organizations_url":"https://api.github.com/users/rstacruz/orgs","repos_url":"https://api.github.com/users/rstacruz/repos","events_url":"https://api.github.com/users/rstacruz/events{/privacy}","received_events_url":"https://api.github.com/users/rstacruz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-12-30T13:08:14Z","updated_at":"2016-01-10T03:11:52Z","closed_at":null,"body":"Hey, i've had a chance to prototype the v2 api and I'd like to share my thoughts on it.\r\n\r\n## Stateless is awesome\r\n\r\nI really love how Deku's component API isn't made with classes. This was one of the things I disliked about React: if components are classes, when are they constructed? How can I access the component instance? Thinking outside classes really drives in the functional and immutable aspect of the API design.\r\n\r\n## But removing setState was a bad idea\r\n\r\nThe biggest change from v2 is the removal of state and instead relying on Redux. I think this can cause a lot of headaches.\r\n\r\nReact's rendering works something like this:\r\n\r\n```js\r\nReactDOM.render = (element) => {\r\n  while (true) {\r\n    tree = render(element) // render components to a virtual dom tree, recursively\r\n\r\n    if (someone called setState()) {\r\n      applyStatesToComponents() // and then render again\r\n    } else {\r\n      break\r\n    }\r\n  }\r\n\r\n  applyChangesToDOM(tree)\r\n}\r\n```\r\n\r\nEffectively, this means 30 components can call `setState()` in one render pass, but re-rendering will only happen once. This is good, because it means we don't re-render 30 times if 30 components want to change states.\r\n\r\n### Using Redux for states\r\nIn contrast, deku v2 asks you to dispatch a store action instead. If 30 components want to change states. This means `store.subscribe(() => { ... })`'s callbacks will be called 30 times, which means re-rendering 30 times.\r\n\r\nAlso, this dispatching can happen /while/ the tree is rendering, causing problems. Consider this naive example:\r\n\r\n```js\r\nexport function onCreate({ path, dispatch }) {\r\n  dispatch({ type: 'UI_SET_STATE', path, values: { loaded_at: +new Date() } })\r\n}\r\n```\r\n\r\nThis is a bad idea, because it means a re-rendering will happen while the onCreate action is executed. You can mitigate this by using `requestAnimationFrame` or `process.nextTick` or similar, so that they happen after rendering:\r\n\r\n```js\r\nexport function onCreate({ path, dispatch }) {\r\n  process.nextTick(() => {\r\n    dispatch({ type: 'UI_SET_STATE', path, values: { loaded_at: +new Date() } })\r\n  })\r\n}\r\n```\r\n\r\nBut this means DOM updates might happen twice, and the rendering is now needlessly asynchronous.\r\n\r\n### Use cases of states\r\n\r\nHere are some use cases for `setState`:\r\n\r\n- a flag to check if the `<img>` loaded completely\r\n- a flag for when the dropdown is open or not\r\n- a movable window's x/y coordinates\r\n\r\n...these transient state flags will only polute the Redux state."},"comment":{"url":"https://api.github.com/repos/dekujs/deku/issues/comments/170305999","html_url":"https://github.com/dekujs/deku/issues/337#issuecomment-170305999","issue_url":"https://api.github.com/repos/dekujs/deku/issues/337","id":170305999,"user":{"login":"ashaffer","id":1871136,"avatar_url":"https://avatars.githubusercontent.com/u/1871136?v=3","gravatar_id":"","url":"https://api.github.com/users/ashaffer","html_url":"https://github.com/ashaffer","followers_url":"https://api.github.com/users/ashaffer/followers","following_url":"https://api.github.com/users/ashaffer/following{/other_user}","gists_url":"https://api.github.com/users/ashaffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ashaffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ashaffer/subscriptions","organizations_url":"https://api.github.com/users/ashaffer/orgs","repos_url":"https://api.github.com/users/ashaffer/repos","events_url":"https://api.github.com/users/ashaffer/events{/privacy}","received_events_url":"https://api.github.com/users/ashaffer/received_events","type":"User","site_admin":false},"created_at":"2016-01-10T03:11:52Z","updated_at":"2016-01-10T03:11:52Z","body":"@rstacruz Ya, I know that's a problem. I'm planning on allowing you to mixin getProp/setProp to redux-ephemeral to support that use-case."}}