{"id":17677478,"url":"https://github.com/unadlib/iflow","last_synced_at":"2025-04-13T00:51:04.052Z","repository":{"id":22341198,"uuid":"95982289","full_name":"unadlib/iflow","owner":"unadlib","description":"Concise \u0026 powerful state management framework for Javascript.","archived":false,"fork":false,"pushed_at":"2022-12-07T17:21:01.000Z","size":2757,"stargazers_count":80,"open_issues_count":47,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-14T08:32:36.116Z","etag":null,"topics":["iflow","react","react-iflow","react-native","state-management"],"latest_commit_sha":null,"homepage":"https://iflow.js.org","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/unadlib.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-07-01T18:55:07.000Z","updated_at":"2023-08-12T16:42:43.000Z","dependencies_parsed_at":"2022-09-08T21:41:43.459Z","dependency_job_id":null,"html_url":"https://github.com/unadlib/iflow","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/unadlib%2Fiflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Fiflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Fiflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unadlib%2Fiflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unadlib","download_url":"https://codeload.github.com/unadlib/iflow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650435,"owners_count":21139672,"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":["iflow","react","react-iflow","react-native","state-management"],"created_at":"2024-10-24T07:28:49.240Z","updated_at":"2025-04-13T00:51:04.028Z","avatar_url":"https://github.com/unadlib.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003ca href='http://iflow.js.org'\u003e\u003cimg src='https://raw.githubusercontent.com/unadlib/iflow/master/assets/logo.png' height='60' alt='iFlow Logo' aria-label='iflow.js.org' /\u003e\u003c/a\u003e\niFlow is a concise \u0026 powerful state management framework, iFlow has no dependencies and it's very small(5k).\n\n[![Travis](https://img.shields.io/travis/unadlib/iflow.svg)](https://travis-ci.org/unadlib/iflow)\n[![Coverage Status](https://coveralls.io/repos/github/unadlib/iflow/badge.svg?branch=master)](https://coveralls.io/github/unadlib/iflow?branch=master)\n[![npm](https://img.shields.io/npm/v/iflow.svg)](https://www.npmjs.com/package/iflow)\n[![Join the chat at https://gitter.im/unadlib/iflow](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/unadlib/iflow?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n\u003e[Implement simple todo in five minutes](https://github.com/unadlib/iflow#implement-simple-todo-in-five-minutes)\n\nIt's dynamic and extensible, you can directly use it to add, delete and reassign the state/action. It completely supports plain class and function based on **mutable data structures**, and be easy to OOP. If you use React, you need use [react-iflow](https://github.com/unadlib/react-iflow) for the connector.\n\n### Features\n* **🎯Plain class and function** - Simple, capable of designing various state structure.\n* **🏬Store tree compose** - Store tree is easy to share and operate.\n* **⚡Dynamic and hot-swapping** - Both the state and action can be directly and freely changed.\n* **💥Async function and other type of functions** - Any actions will be composed or invoked internally.\n* **🚀Powerful middleware** - Middleware can handle any store change event.\n* **🔥Store support immutable** - Store is supported to be processed into a immutable store.\n\n\u003e [Documents](https://iflow.js.org/) / [中文文档](http://cn.iflow.js.org/) \n\n### Contents\n* [Features](https://github.com/unadlib/iflow#features)\n* [Installation](https://github.com/unadlib/iflow#Installation)\n* [Getting started](https://github.com/unadlib/iflow#getting-started)\n    * State\n    * Action\n    * Data flow\n* [Gist](https://github.com/unadlib/iflow#gist)\n* [Implement simple todo in five minutes](https://github.com/unadlib/iflow#implement-simple-todo-in-five-minutes)\n* [Examples](https://github.com/unadlib/iflow#examples)\n* [API Reference](https://github.com/unadlib/iflow#api-reference)\n* [How it works](https://github.com/unadlib/iflow#how-it-works)\n* [Documentation](https://github.com/unadlib/iflow#documentation)\n* [Benefits](https://github.com/unadlib/iflow#benefits)\n* [Limitations and pitfalls](https://github.com/unadlib/iflow#limitations-and-pitfalls)\n* [Support and compatibility](https://github.com/unadlib/iflow#support-and-compatibility)\n* [Change Log](https://github.com/unadlib/iflow#change-log)\n\n### Getting started\n* State\n\u003e support all ECMAScript2015 data types except function, and state can be defined or assigned later.\n```javascript\nimport iFlow from 'iflow'\n\nconst pipe = iFlow({\n  counter: 0,\n})\n```\n* Action\n\u003e support all type functions, and dynamic insert action or remove it.If you use `function`, its function's `this` is the current self pipe store. If you ues `arrow function`, the last argument is the current `self` pipe store.\n```javascript\nimport iFlow from 'iflow'\n\nconst pipe = iFlow({\n  calculate: function(number) {\n    this.counter += number\n  },\n  counter: 0,\n})\n```\n* Data flow\n\u003e View trigger function from `store` action, and run state's setter paths/value, then its setter paths was matched to the components's getter paths, finally decide whether to update\n```javascript\nimport iFlow from 'iflow'\n\nconst pipe = iFlow({\n  calculate: function(number) {\n    this.counter += number\n  },\n  counter: 0,\n})\n\nconst store = pipe.create()\n```\n```javascript\nstore.calculate(1)\nconsole.log(store.counter) // console.log: 1\n```\n### Installation\n```bash\nyarn add iflow\n//or\nnpm install --save iflow\n```\nIf you want to use it completely, you may also need a connector for your Web view framework. For example, you used React and iFlow, and you should use [react-iflow](https://github.com/unadlib/react-iflow) for the connector.\n### Gist\n```javascript\nimport iFlow from 'iflow'\n\nconst pipe = iFlow({\n  calculate: function(number) {\n    this.counter += number\n  },\n  counter: 0,\n})\n\npipe.addObserver((store) =\u003e {\n  console.log(`log '[ store counter ]': `, store.counter)\n})\n\nconst store = pipe.create({counter: 1})\nstore.calculate(1)\n```\n### Implement simple todo in five minutes\n\n1.First we finish quickly a TODO project configuration and basic NPM package dependencies.\n\n```bash\nmkdir example \u0026\u0026 cd example\nyarn init -y\nyarn add -D parcel-bundler babel-cli babel-preset-react babel-preset-env\nyarn add react react-dom iflow react-iflow\n```\n\n2.Then we complete a Babel configuration file and an app portal file index.html\n\n```bash\necho '{\"presets\": [\"env\",\"react\"]}' \u003e .babelrc\necho '\u003cdiv id=\"app\"\u003e\u003c/div\u003e\u003cscript src=\"./index.js\"\u003e\u003c/script\u003e' \u003e index.html\n```\n\n3.And then we complete a simple TODO\n\n```bash\ncat \u003c\u003cEOF \u003e index.js\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport iFlow from 'iflow'\nimport flow from 'react-iflow'\n\nconst store = iFlow({\n    todo: [],\n    add(text){this.todo.push({text})},\n    toggle(item){item.completed = !item.completed}\n}).create()\n\nconst App = flow(store)(class extends React.Component {\n    render() {\n        const {todo,add,toggle} = this.props.store\n        return (\n            \u003cdiv\u003e\n                \u003cinput ref={(ref)=\u003ethis.input=ref}/\u003e\n                \u003cbutton onClick={()=\u003e{add(this.input.value);this.input.value=''}}\u003eAdd\u003c/button\u003e\n                \u003cul\u003e\n                    {todo.map((item,key)=\u003e(\u003cli key={key} style={item.completed?{textDecoration:'line-through'}:{}} onClick={()=\u003etoggle(item)}\u003e{item.text}\u003c/li\u003e))}\n                \u003c/ul\u003e \n            \u003c/div\u003e\n        )\n    }\n})\n\nReactDOM.render(\u003cApp/\u003e,document.getElementById('app'))\nEOF\n```\n\n4.Finally we run up, hey!🎉🎉🎉\n\n```bash\nnpx parcel index.html\n```\n\n### Examples\n* [Counter](https://github.com/unadlib/iflow/tree/master/examples/counter)([Online](https://jsfiddle.net/unadlib/03ukqj5L/))\n* [TODO](https://github.com/unadlib/iflow/tree/master/examples/todo)([Online](https://jsfiddle.net/unadlib/6wabhdqp/))\n\n### API Reference\n* iFlow\n\u003eIt can handle data structures other than function.\n```javascript\nimport iFlow from 'iflow'\n\nconst pipe = iFlow({\n  counter: 0,\n  calculate (number) {\n    this.counter += number\n  }\n})\n```\n```javascript\nimport iFlow from 'iflow'\n\nclass Count {\n  constructor () {\n    this.counter = 0\n  }\n\n  calculate (number) {\n    this.counter += number\n  }\n}\n\nconst pipe = iFlow(new Count())\n```\n```javascript\nimport iFlow from 'iflow'\nconst pipe = iFlow([])\n```\n* middleware()\n\u003eThe Middleware API will Listen to the store any change, and modify it.\n```javascript\npipe.middleware({\n    stateWillInitialize: (...args) =\u003e {},\n    actionWillStart: (...args) =\u003e {},\n    stateWillChange: (...args) =\u003e {},\n    stateDidChange: (...args) =\u003e {},\n    actionDidEnd: (...args) =\u003e {},\n})\n```\n\n* The middleware tables are as follows:\n\n| APIs    | Direct API  | return | return value       | Async  | Description                       |\n| :---------- | :-----------------: | :----: | :----------------: | :---: | ------------------------: | \n| stateWillInitialize        | setInitializeValue  | ✅     | add initialized values    | ❌     | Initialized                |\n| actionWillStart       | addInterceptor      | ✅     | action parameters    | ✅     | Action forward |\n| stateWillChange      | addMiddleware       | ✅     | a setter value       | ❌     | State Change forward|\n| stateDidChange       | addObserver         | ❌     | -                  | ❌     | State Change Notification   | \n| actionDidEnd         | addListener         | ❌     | -                  | ✅     | Action Notification |\n\n* create()\n\u003eEvery pipe will be created with initial value or without.\n```javascript\nconst store = pipe.create({\n  counter: 100,\n})\n```\n\n* batch(action,...paths) / @batch(...paths)\n\u003eIt will batch to update the states\n\n\u003eNo pass the paths arguments, then it will update the pipe store.\n\n```javascript\nconst pipe = iFlow({\n  action: batch(function(){\n    //state changes\n    this.foo.push(1)\n    this.foobar.bar.push(2)\n  })\n})\n```\n```javascript\nconst pipe = iFlow({\n  action: function(){\n    batch(()=\u003e{\n      //state changes\n      this.foo.push(1)\n      this.foobar.bar.push(2)\n    }, 'foo', ['foobar','bar']).call(this)\n  }\n})\n```\n```javascript\nclass Pipe {\n  @batch('foo', ['foobar','bar'])\n  action(){\n    //state changes\n    this.foo.push(1)\n    this.foobar.bar.push(2)\n  }\n}\nconst pipe = iFlow(new Pipe())\n```\n\n### How it works\n![Data Flow](https://raw.githubusercontent.com/unadlib/iflow/master/assets/flowChart.png)\n### Documentation\n\n[Online Documents](https://iflow.js.org)\n* [Introduction](/README.md)\n* [Basics](/docs/basics/README.md)\n* [Advanced](/docs/advanced/README.md)\n* [API](/docs/api/README.md)\n* [Tips](/docs/tips/README.md)\n* [React](/docs/react/README.md)\n* [FAQ](/docs/faq/README.md)\n\n### Benefits\n\n* **Keep the data structure primitive**\n\niFlow because of the proxy mechanism, it retains the primitive nature of the data structure while supporting asynchronous functions as well as other types of functions, including, of course, ordinary classes and functions.\n\n* **No boilerplate code**\n\niFlow can give you more freedom to use it to implement a state data structure that is in line with the actual development needs, and not to have too many boilerplate code because of the limitations of various libraries.\n\n* **Be easy to OOP**\n\nSometimes when we need decoupled business code, we may need some object-oriented programming when design, so the State Library is better if it can support it.\n\n* **As few selectors as possible**\n\nWhen using a web framework such as react, the corresponding connection library [react-iflow](https://github.com/unadlib/react-iflow) allows you to write and manipulate as few selectors as possible.\n\n* **Powerful middleware**\n\nIf necessary, in fact iFlow's middleware is powerful and useful, and you can use it to implement a variety of coupled codes.\n\n* **Composable and scalable store**\n\niFlow advocates the store group to synthesize the store tree without worrying about the performance impact of the unrelated store, because it is dynamically matched and you can be assured of free combination and expansion of the store.\n\n### Limitations and pitfalls\n\n* [No scheduler updates within automatic batch processing](https://github.com/unadlib/iflow/issues/3)\n\nFor the action of a normal synchronization process, the merge problem with the same state being changed multiple times is ignored and we will fix it.\n\n\n* [Proxy/Reflect polyfill not supported](https://github.com/unadlib/iflow/issues/2)\n\nSince IE11 does not support ES6 Proxy/Reflect, we will consider adding Proxy/Reflect polyfill to support IE11.\n\n\n* [A prototype chain function injection of a primitive type that does not support native proxy cannot trigger notification of these types of change behavior automatically](https://github.com/unadlib/iflow/issues/4)\n\nCurrently known unsupported types are: `Set` / `WeakSet` / `Map` / `WeakMap`, and soon we will support it.\n\n### Support and compatibility\n\n| Browsers          |  Chrome    | IE    | Edge  | FireFox  | Safari  | Opera   | Node    |\n| :---------------- | :--------: | :---: | :---: | :------: | :-----: | :-----: | :------: |\n| Supported         | ✅         |  ❌   |  ✅    |  ✅      |  ✅     |  ✅     |  ✅     |\n| Version           |   49+      |  -    |  12+  |  18+     |  10+    |  36+    |  6.4.0+ |\n\n### Change Log\n* Completed immutable store\n* Completed alpha version\n### License\n\n---\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funadlib%2Fiflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funadlib%2Fiflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funadlib%2Fiflow/lists"}