{"id":25878263,"url":"https://github.com/skrivle/react-stateful-component","last_synced_at":"2025-03-02T12:23:10.904Z","repository":{"id":57345314,"uuid":"109510114","full_name":"skrivle/react-stateful-component","owner":"skrivle","description":"Functional stateful  React components with sideEffect support","archived":false,"fork":false,"pushed_at":"2019-01-31T06:53:50.000Z","size":3268,"stargazers_count":19,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-15T08:30:51.916Z","etag":null,"topics":["component","flow","flowtype","functional","javascript","react","reducer","side-effects","state-management","subscriptions"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skrivle.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-04T16:15:13.000Z","updated_at":"2023-05-08T13:25:47.000Z","dependencies_parsed_at":"2022-09-15T16:21:29.944Z","dependency_job_id":null,"html_url":"https://github.com/skrivle/react-stateful-component","commit_stats":null,"previous_names":["vejersele/react-stateful-component"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skrivle%2Freact-stateful-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skrivle%2Freact-stateful-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skrivle%2Freact-stateful-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skrivle%2Freact-stateful-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skrivle","download_url":"https://codeload.github.com/skrivle/react-stateful-component/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241504323,"owners_count":19973219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","flow","flowtype","functional","javascript","react","reducer","side-effects","state-management","subscriptions"],"created_at":"2025-03-02T12:23:10.404Z","updated_at":"2025-03-02T12:23:10.881Z","avatar_url":"https://github.com/skrivle.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Stateful Component\n\n[![Build Status](https://travis-ci.org/vejersele/react-stateful-component.svg?branch=master)](https://travis-ci.org/vejersele/react-stateful-component)\n\nCreate stateful React components in a functional way, with side effect support. Heavily inspired by\nReasonReact's api.\n\n*   Uses a reducer to manage state\n*   The reducer can schedule side effects following the same pattern as Elm and Reason-React\n*   Side effects are run outside of the component, meaning you can test your components without having\n    to execute side effects\n*   life cycle hooks\n*   Subscriptions to handle communication with the \"outside world\"\n*   Static type checking with Flow\n\n### \u003e [React Stateful Component Documentation](packages/react-stateful-component)\n\n### \u003e [TodoMVC example](https://github.com/vejersele/react-stateful-component-todo)\n\n## Making the case for functional stateful components.\n\n### State management\n\nReact class components aren't always easy to keep maintainable, and it gets harder as the amount of\nstate the component is managing grows. As setState() calls get spread across multiple methods, it\nbecomes more difficult to have a good understanding of what state changes are happening within the\ncomponent.\n\nRedux has provided us with a very good solution to this problem. It uses pure reducer functions and\na store to centralise your state management. However Redux also comes with some downsides when\nworking on larger apps.\n\nWhen building larger apps, you typically want to separate your app into multiple smaller apps or\nfeatures. Each of these mini apps having their own responsibilities and thus their own state to\nmanage. While Redux provides us with the ability to have separate state branches for these\nindividual mini apps, the state still lives in the same single store. This can sometimes lead to\nstate that gets shared and actions that get reduced by multiple mini apps, creating a dependency\nbetween different sub sections of your app. Of course this isn't always a downside, sometimes it's\neven desirable, but in some situations you want to enforce that separation a little bit more.\n\nReact Stateful Component allows you to do that because it's state is scoped to the component (it's\njust a React class component behind the scenes).\n\nAnother benefit of using component scoped state is that it can be wired on the fly. As features may\nlive in different sub sections of your app, you don't want to wire all of your state up front.\nInstead you want it to be available whenever you need it. Having the state scoped to the component\nalso helps with code splitting.\n\n### Side effects\n\nIn order to keep a component clean and testable we want to push everything that isn't related to\nreducing actions and managing state into a side effect. By doing this you can easily unit test a\ncomponent without having to worry about api calls, timeouts, web sockets, etc ... This mean you can\nunit test your reducer and verify the state that is returned from it, or check if a certain action\ntriggers the right side effect. But this also means that you can test the complete component using a\ntool like Airbnb's enzyme, without having to worry about the side effects.\n\nReact Stateful Component uses a SideEffectProvider to run side effects. This means that a component\nwill never execute side effects itself it will only schedule them.\n\nUsing the MockSideEffectProvider provided by\n[react-stateful-component-tools](packages/react-stateful-component-tools), you can intercept\nscheduled side effects, and if needed dispatch to desired actions in your tests.\n\nLike in Elm and ReactReason, side effects are scheduled from within the reducer. Side effect are\nregular functions receiving reduce() as a parameter. Meaning you don't have to deal with complex\nside effect models.\n\n## Code sample\n\n```javascript\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport createComponent, { update, SideEffectProvider } from 'react-stateful-component';\n\n// Actions\nconst add = () =\u003e ({ type: 'ADD' });\nconst subtract = () =\u003e ({ type: 'SUBTRACT' });\n\nconst Counter = createComponent(() =\u003e ({\n    initialState: () =\u003e ({\n        counter: 0\n    }),\n    reducer: (state, action) =\u003e {\n        const { counter } = state;\n\n        switch (action.type) {\n            case 'ADD':\n                return update.state({ counter: counter + 1 });\n            case 'SUBTRACT':\n                return update.state({ counter: counter - 1 });\n            default:\n                return update.nothing();\n        }\n    },\n    render: ({ state: { counter }, reduce }) =\u003e (\n        \u003cdiv\u003e\n            \u003cbutton onClick={() =\u003e reduce(add())}\u003e+\u003c/button\u003e\n            \u003cspan\u003e{counter}\u003c/span\u003e\n            \u003cbutton onClick={() =\u003e reduce(subtract())}\u003e-\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}));\n\nReactDOM.render(\n    \u003cSideEffectProvider\u003e\n        \u003cCounter /\u003e\n    \u003c/SideEffectProvider\u003e,\n    document.getElementById('app')\n);\n```\n\n## Examples\n\nAn example directory is included in this repo. You can check it out locally by running:\n\n```\ngit clone https://github.com/vejersele/react-stateful-component.git\ncd react-stateful-component\nnpm install\nnpm run storybook\n```\n\nthis will start storybook on http://localhost:6006/\n\n## Contributing\n\nfeel free to open issues and pr's!\n\nrunning tests:\n\n```\nnpm test\n```\n\nRun these two commands in two separate terminal instances to re-run tests on each change:\n\n```\nnpm run build:watch\nnpm run test:watch\n```\n\n## Inspiration\n\nhttps://reasonml.github.io/reason-react/\n\nhttp://elm-lang.org/\n\nhttps://redux.js.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskrivle%2Freact-stateful-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskrivle%2Freact-stateful-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskrivle%2Freact-stateful-component/lists"}