{"id":13781586,"url":"https://github.com/Microsoft/satcheljs","last_synced_at":"2025-05-11T15:31:55.217Z","repository":{"id":40649951,"uuid":"64699055","full_name":"microsoft/satcheljs","owner":"microsoft","description":"Satchel is a data store based on the Flux architecture.  It is characterized by exposing an observable state that makes view updates painless and efficient.","archived":false,"fork":false,"pushed_at":"2024-07-29T22:48:06.000Z","size":1635,"stargazers_count":394,"open_issues_count":15,"forks_count":28,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-07T23:47:43.277Z","etag":null,"topics":["flux","flux-architecture","hacktoberfest","mobx","react"],"latest_commit_sha":null,"homepage":"https://microsoft.github.io/satcheljs","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-01T20:24:52.000Z","updated_at":"2025-04-04T02:04:31.000Z","dependencies_parsed_at":"2024-01-15T21:49:19.903Z","dependency_job_id":"f958bf8d-4fe6-44f6-b537-2438d905e079","html_url":"https://github.com/microsoft/satcheljs","commit_stats":null,"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fsatcheljs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fsatcheljs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fsatcheljs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2Fsatcheljs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microsoft","download_url":"https://codeload.github.com/microsoft/satcheljs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253588566,"owners_count":21932278,"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":["flux","flux-architecture","hacktoberfest","mobx","react"],"created_at":"2024-08-03T18:01:27.379Z","updated_at":"2025-05-11T15:31:54.918Z","avatar_url":"https://github.com/microsoft.png","language":"TypeScript","funding_links":[],"categories":["List"],"sub_categories":[],"readme":"# Satchel\n\nSatchel is a dataflow framework based on the [Flux architecture](http://facebook.github.io/react/blog/2014/05/06/flux.html).  It is characterized by exposing an observable state that makes view updates painless and efficient.\n\n[![npm](https://img.shields.io/npm/v/satcheljs.svg)](https://www.npmjs.com/package/satcheljs)\n[![Build Status](https://travis-ci.org/Microsoft/satcheljs.svg?branch=master)](https://travis-ci.org/Microsoft/satcheljs)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Influences\n\nSatchel is an attempt to synthesize the best of several dataflow patterns typically used to drive a React-based UI.  In particular:\n\n* [Flux](http://facebook.github.io/react/blog/2014/05/06/flux.html) is not a library itself, but is a dataflow pattern conceived for use with React.  In Flux, dataflow is unidirectional, and the only way to modify state is by dispatching actions through a central dispatcher.\n* [Redux](http://redux.js.org/index.html) is an implementation of Flux that consolidates stores into a single state tree and attempts to simplify state changes by making all mutations via pure functions called reducers.  Ultimately, however, we found reducers and immutable state cumbersome to deal with, particularly in a large, interconnected app.\n* [MobX](http://mobxjs.github.io/mobx/index.html) provides a seamless way to make state observable, and allows React to listen to state changes and rerender in a very performant way.  Satchel uses MobX under the covers to allow React components to observe the data they depend on.\n\n## Advantages\n\nThere are a number of advantages to using Satchel to maintain your application state:\n\n* Satchel enables a very **performant UI**, only rerendering the minimal amount necessary.  MobX makes UI updates very efficient by automatically detecting specifically what components need to rerender for a given state change.\n* Satchel's datastore allows for **isomorphic JavaScript** by making it feasible to render on the server and then serialize and pass the application state down to the client.\n* Satchel supports **middleware** that can act on each action that is dispatched.  (For example, for tracing or performance instrumentation.)\n* Satchel is **type-safe** out of the box, without any extra effort on the consumer's part.\n\n## Installation\n\nInstall via NPM:\n\n`npm install satcheljs --save`\n\nIn order to use Satchel with React, you'll also need MobX and the MobX React bindings:\n\n`npm install mobx --save`\n\n`npm install mobx-react --save`\n\n## Usage\n\nThe following examples assume you're developing in Typescript.\n\n### Create a store with some initial state\n\n```typescript\nimport { createStore } from 'satcheljs';\n\nlet getStore = createStore(\n    'todoStore',\n    { todos: [] }\n);\n```\n\n### Create a component that consumes your state\n\nNotice the `@observer` decorator on the component—this is what tells MobX to rerender the component whenever the data it relies on changes.\n\n```javascript\nimport { observer } from 'mobx-react';\n\n@observer\nclass TodoListComponent extends React.Component\u003cany, any\u003e {\n    render() {\n        return (\n            \u003cdiv\u003e\n                {getStore().todos.map(todo =\u003e \u003cdiv\u003e{todo.text}\u003c/div\u003e)}\n            \u003c/div\u003e\n        );\n    }\n}\n```\n\n### Implement an action creator\n\nNote that, as a convenience, Satchel action creators created with the `action` API both *create* and *dispatch* the action.\nThis is typically how you want to use action creators.\nIf you want to create and dispatch the actions separately you can use the `actionCreator` and `dispatch` APIs.\n\n```typescript\nimport { action } from 'satcheljs';\n\nlet addTodo = action(\n    'ADD_TODO',\n    (text: string) =\u003e ({ text: text })\n);\n\n// This creates and dispatches an ADD_TODO action\naddTodo('Take out trash');\n```\n\n### Implement a mutator\n\nYou specify what action a mutator subscribes to by providing the corresponding action creator.\nIf you're using TypeScript, the type of `actionMessage` is automatically inferred.\n\n```typescript\nimport { mutator } from 'satcheljs';\n\nmutator(addTodo, (actionMessage) =\u003e {\n    getStore().todos.push({\n        id: Math.random(),\n        text: actionMessage.text\n    });\n};\n```\n\n### Orchestrators\n\nOrchestrators are like mutators—they subscribe to actions—but they serve a different purpose.\nWhile mutators modify the store, orchestrators are responsible for side effects.\nSide effects might include making a server call or even dispatching further actions.\n\nThe following example shows how an orchestrator can persist a value to a server before updating the store.\n\n```typescript\nimport { action, orchestrator } from 'satcheljs';\n\nlet requestAddTodo = action(\n    'REQUEST_ADD_TODO',\n    (text: string) =\u003e ({ text: text })\n);\n\norchestrator(requestAddTodo, async (actionMessage) =\u003e {\n    await addTodoOnServer(actionMessage.text);\n    addTodo(actionMessage.text);\n});\n```\n\n### mutatorAction\n\nIn many cases a given action only needs to be handled by one mutator.\nSatchel provides this utility API which encapsulates action creation, dispatch, and handling in one simple function call.\n\nThe `addTodo` mutator above could be implemented as follows:\n\n```typescript\nlet addTodo = mutatorAction(\n    'ADD_TODO',\n    function addTodo(text: string) {\n        getStore().todos.push({\n            id: Math.random(),\n            text: actionMessage.text\n        });\n    });\n```\n\nThis is a succinct and easy way to write mutators, but it comes with a restriction:\nthe action creator is not exposed, so no *other* mutators or orchestrators can subscribe to it.\nIf an action needs multiple handlers then it must use the full pattern with action creators and handlers implemented separately.\n\n## License - MIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMicrosoft%2Fsatcheljs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMicrosoft%2Fsatcheljs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMicrosoft%2Fsatcheljs/lists"}