{"id":19279034,"url":"https://github.com/krasimir/fluxiny","last_synced_at":"2025-04-22T00:32:20.796Z","repository":{"id":48183064,"uuid":"47740333","full_name":"krasimir/fluxiny","owner":"krasimir","description":"~1K implementation of flux architecture","archived":false,"fork":false,"pushed_at":"2017-11-23T12:05:37.000Z","size":778,"stargazers_count":78,"open_issues_count":1,"forks_count":5,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-10-02T07:28:32.495Z","etag":null,"topics":["facebook","flux","flux-architecture","javascript","react"],"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/krasimir.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":"2015-12-10T05:32:57.000Z","updated_at":"2023-03-11T12:19:50.000Z","dependencies_parsed_at":"2022-09-26T19:34:46.752Z","dependency_job_id":null,"html_url":"https://github.com/krasimir/fluxiny","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Ffluxiny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Ffluxiny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Ffluxiny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Ffluxiny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krasimir","download_url":"https://codeload.github.com/krasimir/fluxiny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223883712,"owners_count":17219270,"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":["facebook","flux","flux-architecture","javascript","react"],"created_at":"2024-11-09T21:13:05.765Z","updated_at":"2024-11-09T21:13:06.361Z","avatar_url":"https://github.com/krasimir.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fluxiny\n\n\u003e [Flux architecture](https://facebook.github.io/flux/docs/overview.html) implemented in ~100 lines of code.\n\n![Flux](http://krasimirtsonev.com/blog/articles/fluxiny/fluxiny_basic_flux_architecture.jpg)\n\n[Flux](http://facebook.github.io/flux/) is an architectural design pattern for building user interfaces. It was introduced by Facebook at their [F8](https://youtu.be/nYkdrAPrdcw?t=568) conference. Since then, lots of companies adopted the idea and it seems like a good pattern for building front-end apps. Flux is very often used with [React](http://facebook.github.io/react/). Another library released by Facebook. I myself use React+Flux in my [daily job](http://trialreach.com/) and I could say that the simplicity is one of the main benefits. This combination helps creating apps faster and at the same time keeps the code well organized. This library is a result of my experience using the pattern. I'm a big fan of simple and small, almost vanilla written JavaScript libraries. So, Fluxiny is created in the same manner.\n\n---\n\n#### Store\n\nThe Store in the context of Fluxiny is just a plain JavaScript object with an `update` method:\n\n```js\nvar Store = {\n  update: function (action, change) {\n    // ...\n  }\n};\n```\n\n`action.type` contains the type of the dispatched action. In order to notify the view that the store updated its data we call the `change` method.\n\n#### Action\n\nThe action is a JavaScript object with two properties - `type` and `payload`. `type` is usually a string and `payload` could be anything. We however don't create such objects. They are generated by Fluxiny. What we use in our app is a function representing the action. Once it's called the dispatcher sends the action to all the stores.\n\n```\nimport Fluxiny from 'fluxiny';\nconst { createAction } = Fluxiny.create();\n\nvar action = createAction('SOMETHING_HAPPENED');\n\n  // ... somewhere in the view\n  action({ customProp: 'this is the payload' });\n```\n\nAll we have to do is calling the action function and if we need to attach some data we pass it as an argument.\n\n#### Dispatcher\n\nWe don't need a dispatcher. There is such but it's used by Fluxiny internally. The library is designed like that so the developer simply doesn't need it.\n\n#### View\n\nThe view could be anything. As long as it has an access to a `subscriber` function. If it updates its state based on changes in the store we could say that satisfies the Flux pattern.\n\n```js\nvar Store = {\n  _data: { value: 0 },\n  update: function (action, change) {\n    // ... calculate the value\n    change();\n  },\n  getValue: function () {\n    return this._data.value;\n  }\n};\n\nvar subscriber = createSubscriber(store);\n\nvar View = function() {\n  var state = { value: 0 };\n\n  subscriber(function (store) {\n    state.value = store.getValue();\n  });\n};\n\n``` \n\n## Fluxiny public API\n\nThe library exports only two methods. That's it. There are no base classes for extending.\n\n```js\nimport Fluxiny from 'fluxiny';\nconst { createSubscriber, createAction } = Fluxiny.create();\n```\n\n* `createSubscriber` accepts our store and returns a subscriber function. \n* `createAction` accepts a string (type of action) and returns a dispatching function.\n\n## Processes\n\nHere are the main processes in the context of library:\n\n#### Registering a store into the dispatcher\n\n```js\nvar Store = { \n  update: function (action, change) { \n    // ...\n  }\n};\nvar subscriber = createSubscriber(Store);\n```\n\n#### Mutating the state of the store and notifying the view\n\nThe `update` method of the store accepts two arguments. An `action` with signature `{ type, payload }` and a function `change`. The store updates its internal state based on `action.type` and then fires `change()` notifying the view for that change.\n\n```js\nvar Store = { \n  _data: { value: 0 },\n  update: function (action, change) { \n    if (action.type === 'increase') {\n      // mutation of the data\n      this._data.value += action.payload;\n      // notifying all subscribed views that the data is changed\n      change();\n    }\n  }\n};\n```\n\n#### Subscribing the view to changes in the store\n\n```js\nvar Store = { \n  _data: { value: 0 },\n  update: function (action, change) { \n    // updates _data.value\n    change();\n  },\n  getValue: function () {\n    return this._data.value;\n  }\n};\nvar storeSubscriber = createSubscriber(Store);\n\nvar View = function (subscriber) {\n  var counterValue;\n\n  subscriber(function consumer(store) {\n    // updating the internal state of the view\n    counterValue = store.getValue();\n    // probably calling the render method\n    // of the view\n  });\n};\n\nView(storeSubscriber);\n\n```\nNotice how we need a getter in the store so the view could fetch the needed information. In Fluxiny the view says what it needs from the store and not the store pushes data to the view.\n\n*Note that the `consumer` function is called at least once by default.*\n\n#### Dispatching an action\n\nFluxiny uses the action-creator pattern. We specify the type of the action and as a result we get a function. Calling that function means dispatching the event. For example:\n\n```js\nvar increaseAction = createAction('increase');\n\nvar View = function (subscriber, increaseAction) {\n  // ...\n  increaseButton.addEventListener('click', increaseAction);\n};\n\nView(subscriber, increaseAction);\n```\n\nIn the example above all the stores will receive an action with `type` equal to `increase` and `payload` equal to mouse event object. Or in other words what we pass to `increaseAction` is attached to `payload` property of the action. In this particular example the browser sends an event object.\n\n## Setup\n\nAs a script tag directly in the browser:\n\n```html\n\u003cscript src=\"fluxiny.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  var Flux = Fluxiny.create();\n  // Flux.createSubscriber\n  // Flux.createAction\n\u003c/script\u003e\n```\n\nVia npm:\n\n```\nnpm install fluxiny\n```\n\nThen simply import the module with\n\n```js\n// var Fluxiny = require('fluxiny');\nimport Fluxiny from 'fluxiny';\n```\n\n## Testing\n\nRun the following command:\n\n```\nnpm install \u0026\u0026 npm run test\n```\n\n![tests](./imgs/tests.jpg)\n\n## Resources\n\n* [Dissection of Flux architecture or how to write your own](http://krasimirtsonev.com/blog/article/dissection-of-flux-architecture-or-how-to-write-your-own-react)\n* Simple live demo of Fluxiny - [jsfiddle.net/krasimir/w0ne11bh](https://jsfiddle.net/krasimir/w0ne11bh/)\n* Live demo using React - [krasimir.github.io/fluxiny/example/](http://krasimir.github.io/fluxiny/example/) and source code [here](https://github.com/krasimir/fluxiny/tree/master/example).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrasimir%2Ffluxiny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrasimir%2Ffluxiny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrasimir%2Ffluxiny/lists"}