{"action":"created","issue":{"url":"https://api.github.com/repos/reactjs/redux/issues/1051","repository_url":"https://api.github.com/repos/reactjs/redux","labels_url":"https://api.github.com/repos/reactjs/redux/issues/1051/labels{/name}","comments_url":"https://api.github.com/repos/reactjs/redux/issues/1051/comments","events_url":"https://api.github.com/repos/reactjs/redux/issues/1051/events","html_url":"https://github.com/reactjs/redux/issues/1051","id":117672002,"number":1051,"title":"Shortcomings of the current applyMiddleware and composing createStore.","user":{"login":"joonhocho","id":930795,"avatar_url":"https://avatars.githubusercontent.com/u/930795?v=3","gravatar_id":"","url":"https://api.github.com/users/joonhocho","html_url":"https://github.com/joonhocho","followers_url":"https://api.github.com/users/joonhocho/followers","following_url":"https://api.github.com/users/joonhocho/following{/other_user}","gists_url":"https://api.github.com/users/joonhocho/gists{/gist_id}","starred_url":"https://api.github.com/users/joonhocho/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joonhocho/subscriptions","organizations_url":"https://api.github.com/users/joonhocho/orgs","repos_url":"https://api.github.com/users/joonhocho/repos","events_url":"https://api.github.com/users/joonhocho/events{/privacy}","received_events_url":"https://api.github.com/users/joonhocho/received_events","type":"User","site_admin":false},"labels":[{"id":225483567,"url":"https://api.github.com/repos/reactjs/redux/labels/discussion","name":"discussion","color":"fbca04","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":26,"created_at":"2015-11-18T20:17:02Z","updated_at":"2016-11-04T17:26:06Z","closed_at":"2016-01-28T02:57:30Z","body":"``` javascript\nexport default function applyMiddleware(...middlewares) {\n  return (next) => (reducer, initialState) => {\n    var store = next(reducer, initialState)\n    var dispatch = store.dispatch\n    var chain = []\n\n    var middlewareAPI = {\n      getState: store.getState,\n      dispatch: (action) => dispatch(action)\n    }\n    chain = middlewares.map(middleware => middleware(middlewareAPI))\n    dispatch = compose(...chain)(store.dispatch)\n\n    return {\n      ...store,\n      dispatch\n    }\n  }\n}\n```\n\nLooking at the source code above, `applyMiddleware` creates a new `store` object and overrides `dispatch` with newly composed dispatch, and returns the new `store`.\n\nThere are shortcomings of this approach that I have experienced.\nTake a look at the following scenario:\n\n``` javascript\ncompose(\n  applyMiddleware(A),\n  reduxRouter(...),\n  applyMiddleware(B)\n)(createStore)\n```\n\nBecause of the current implementation of `applyMiddleware` and `compose` to enhance `createStore`, \nmiddleware A and middleware B will not share the same `dispatch`.\nThat means `dispatch(action)` in A and `dispatch(action)` in B will go through different code paths and may yield completely different outcomes, and it's confusing and difficult to debug.\nAlso, there is no way for middleware A to dispatch any reduxRouter actions such as `pushState`, `replaceState`, etc as those actions will never go through reduxRouter middleware.\n\nMy proposed solution would be:\n1. Create only one `store` instance, and do not replace it by `compose`ing `createStore`.\n2. Enhance it by composing and replacing `dispatch` function on the only `store` instance.\n3. Share the `store`, not `dispatch` across all middlewares.\n\nThis way, there is only one universal `store` instance, and `store.dispatch` will always go through the same code path and yield the same outcome regardless of which middleware.\n"},"comment":{"url":"https://api.github.com/repos/reactjs/redux/issues/comments/258495366","html_url":"https://github.com/reactjs/redux/issues/1051#issuecomment-258495366","issue_url":"https://api.github.com/repos/reactjs/redux/issues/1051","id":258495366,"user":{"login":"mauron85","id":359450,"avatar_url":"https://avatars.githubusercontent.com/u/359450?v=3","gravatar_id":"","url":"https://api.github.com/users/mauron85","html_url":"https://github.com/mauron85","followers_url":"https://api.github.com/users/mauron85/followers","following_url":"https://api.github.com/users/mauron85/following{/other_user}","gists_url":"https://api.github.com/users/mauron85/gists{/gist_id}","starred_url":"https://api.github.com/users/mauron85/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mauron85/subscriptions","organizations_url":"https://api.github.com/users/mauron85/orgs","repos_url":"https://api.github.com/users/mauron85/repos","events_url":"https://api.github.com/users/mauron85/events{/privacy}","received_events_url":"https://api.github.com/users/mauron85/received_events","type":"User","site_admin":false},"created_at":"2016-11-04T17:26:06Z","updated_at":"2016-11-04T17:26:06Z","body":">is there a specific reason why you would want to put that before applyMiddleware?\r\n\r\nyeah, it any other case I would not work. I believe it's because it's because it's main purpose is to translate redux-loop effects into actions. All the magic is done in this redux-loop enhancer:\r\nhttps://github.com/redux-loop/redux-loop/blob/0da84e946e2b262f98c836ad310fcd0d80bee94d/modules/install.js#L29\r\n\r\nIt add effect into currentEffect batch and returns model, which I believe is redux action."}}
{"actor":{"display_login":"mauron85"}}