{"action":"created","issue":{"url":"https://api.github.com/repos/reactjs/react-redux/issues/278","repository_url":"https://api.github.com/repos/reactjs/react-redux","labels_url":"https://api.github.com/repos/reactjs/react-redux/issues/278/labels{/name}","comments_url":"https://api.github.com/repos/reactjs/react-redux/issues/278/comments","events_url":"https://api.github.com/repos/reactjs/react-redux/issues/278/events","html_url":"https://github.com/reactjs/react-redux/issues/278","id":130830352,"number":278,"title":"RFC: Reuse complex components implemented in React plus Redux","user":{"login":"sompylasar","id":498274,"avatar_url":"https://avatars1.githubusercontent.com/u/498274?v=3","gravatar_id":"","url":"https://api.github.com/users/sompylasar","html_url":"https://github.com/sompylasar","followers_url":"https://api.github.com/users/sompylasar/followers","following_url":"https://api.github.com/users/sompylasar/following{/other_user}","gists_url":"https://api.github.com/users/sompylasar/gists{/gist_id}","starred_url":"https://api.github.com/users/sompylasar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sompylasar/subscriptions","organizations_url":"https://api.github.com/users/sompylasar/orgs","repos_url":"https://api.github.com/users/sompylasar/repos","events_url":"https://api.github.com/users/sompylasar/events{/privacy}","received_events_url":"https://api.github.com/users/sompylasar/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":15,"created_at":"2016-02-02T21:54:49Z","updated_at":"2017-06-22T13:34:24Z","closed_at":null,"body":"This post is meant to be a start for a discussion. [Moved from here](https://github.com/reactjs/redux/issues/1353#issuecomment-178781992) as @gaearon [suggested here](https://github.com/reactjs/redux/issues/1353#issuecomment-178783973).\r\n## Intro\r\n\r\nI'm interested in finding best practices on how to architect complex components implemented in React and Redux so that they are reusable as a whole in another app.\r\n\r\nNot sure how widespread is the problem, but I encounter it from time to time. I hope the developers from the front-end community encounter similar problems, too.\r\n## Terms and definitions\r\n\r\nA **complex component** -- a UI (React, Redux actions), coupled with business logic (Redux reducer), and data access logic (Redux actions' side effects; middleware).\r\n\r\nTraits of a complex component:\r\n- can be instantiated more than once, maybe simultaneously (not a singleton)\r\n- each instance can have its own configuration\r\n- can query and manipulate the global environment:\r\n  - the URL and the history (routing, back-forward)\r\n  - network communication (AJAX, WebSockets etc.)\r\n  - storage (cookie, localStorage, sessionStorage etc.)\r\n  - viewport dimensions, global events like viewport scrolling/resizing\r\n- can depend on the app state:\r\n  - query and manipulate other components\r\n  - delegate some functionality, e.g. asset loading, full-screen modal container etc.\r\n- should not pollute the environment\r\n- when used from another app, the component should be reused, not copy-pasted\r\n\r\nAn **app** -- a UI environment where the components are configured and instantiated.\r\n\r\nTraits of an app to consider:\r\n- can be a React + Redux app\r\n- can be a React-only app\r\n- can be a non-React app\r\n## Examples of components\r\n- a [wizard](http://ui-patterns.com/patterns/Wizard), a multi-step form, a [questionnaire](https://en.wikipedia.org/wiki/Questionnaire)\r\n- a complex stateful popup, like a multi-tab settings dialog, or a chat\r\n- a WYSIWYG editor with autocompletion and image uploads\r\n\r\nDeveloping such components with Redux adds the invaluable benefits of predictability and replayability.\r\n## Questions to answer\r\n- How to structure the component code (where to put reducers, actions, UI code)\r\n- How to put a component into a React + Redux app\r\n- How to put a component into an app that has no Redux and/or React\r\n- How to isolate the state of the component instance\r\n- How to configure the component reducers' logic based on the component instance configuration\r\n- How to target actions at specific component instances' state\r\n- How to handle actions of a specific component instance in the app reducers\r\n- How to bridge the component with the global environment (URL and history, network, storage)\r\n- How to bridge the component with the app state\r\n- How to bridge the component with the functionality provided by an app (asset loading, full-screen modal container etc.)\r\n\r\nReact developers from Facebook answered that I should \"start by reusing React components only\", but having a lot of business logic copied from app to app is not the best way to go.\r\n\r\nElm architecture answers some of the questions, but Redux is quite different (no view+reducer coupling, no explicit serializable side-effects).\r\n## References\r\n- Similar discussion, but not so broad: https://github.com/reactjs/react-redux/issues/123\r\n- Similar discussion, but about just actions / reducers / side-effects: https://github.com/reactjs/redux/issues/1171\r\n- Similar question: https://github.com/reactjs/redux/issues/1314\r\n- Related: https://github.com/yelouafi/redux-saga/issues/62 Though I'd like to avoid sticking to redux-saga until these sagas' state is serializable as well as redux state to at least survive a page reload. ( https://github.com/yelouafi/redux-saga/issues/22, https://github.com/yelouafi/redux-saga/issues/5 )\r\n- Related: https://github.com/reactjs/redux/issues/1098\r\n- Related, about action types convention: https://github.com/reactjs/redux/issues/786\r\n- Related: https://github.com/reactjs/redux/issues/913\r\n- Related: https://github.com/reactjs/redux/issues/943#issuecomment-150712338\r\n- Related, reducer logic customization: [BurntCaramel/flambeau reducer props](https://github.com/BurntCaramel/flambeau/blob/master/docs/reducers.md#props)\r\n- https://github.com/erikras/redux-form\r\n- https://github.com/tonyhb/redux-ui\r\n- https://github.com/erikras/multireducer\r\n- https://github.com/acdlite/reduce-reducers\r\n- https://github.com/artsy/react-redux-controller\r\n- https://github.com/Wildhoney/ReduxLocal\r\n- https://github.com/gcazaciuc/redux-fractal\r\n- https://github.com/tomchentw-deprecated/redux-component\r\n- https://github.com/wcjohnson/redux-components "},"comment":{"url":"https://api.github.com/repos/reactjs/react-redux/issues/comments/310381564","html_url":"https://github.com/reactjs/react-redux/issues/278#issuecomment-310381564","issue_url":"https://api.github.com/repos/reactjs/react-redux/issues/278","id":310381564,"user":{"login":"mpeyper","id":23029903,"avatar_url":"https://avatars3.githubusercontent.com/u/23029903?v=3","gravatar_id":"","url":"https://api.github.com/users/mpeyper","html_url":"https://github.com/mpeyper","followers_url":"https://api.github.com/users/mpeyper/followers","following_url":"https://api.github.com/users/mpeyper/following{/other_user}","gists_url":"https://api.github.com/users/mpeyper/gists{/gist_id}","starred_url":"https://api.github.com/users/mpeyper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mpeyper/subscriptions","organizations_url":"https://api.github.com/users/mpeyper/orgs","repos_url":"https://api.github.com/users/mpeyper/repos","events_url":"https://api.github.com/users/mpeyper/events{/privacy}","received_events_url":"https://api.github.com/users/mpeyper/received_events","type":"User","site_admin":false},"created_at":"2017-06-22T13:34:24Z","updated_at":"2017-06-22T13:34:24Z","body":"Just stumbled across this discussion and thought I'd drop a link in to my library for solving this problem, [redux-subspace](https://github.com/ioof-holdings/redux-subspace).  It creates a **sub**-store (backed by the root store) and can automatically name**space** actions to isolate them from the parent components.\r\n\r\nIt has been designed so that the complex child components (which we have dubbed micro-frontends, but we have used it on really small complex components too) are completely unaware that they are in a \"subspace\" instead of a regular react-redux provider.  The parent component decides where in it's state (which could also be a subspace for all it knows) the child component's state is kept which make it really resilient to refactoring, multi-instance and reuse in multiple apps (we use redux-subspace for all these cases)."}}
{"actor":{"display_login":"mpeyper"}}