{"id":13452127,"url":"https://github.com/thefrontside/microstates","last_synced_at":"2025-05-15T07:06:20.497Z","repository":{"id":41596253,"uuid":"61859738","full_name":"thefrontside/microstates","owner":"thefrontside","description":"Composable state primitives for JavaScript","archived":false,"fork":false,"pushed_at":"2023-03-04T03:29:16.000Z","size":11270,"stargazers_count":1313,"open_issues_count":60,"forks_count":53,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-14T12:58:41.720Z","etag":null,"topics":["batch-transitions","composition","lens","microstates","state-machines","transition"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thefrontside.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-06-24T05:45:06.000Z","updated_at":"2025-04-01T18:47:00.000Z","dependencies_parsed_at":"2023-02-05T02:01:46.024Z","dependency_job_id":"b576d0ab-4b5e-45f4-bf65-eb0e5516972d","html_url":"https://github.com/thefrontside/microstates","commit_stats":{"total_commits":475,"total_committers":33,"mean_commits":"14.393939393939394","dds":0.5305263157894737,"last_synced_commit":"0d97fe73ec9a43012a5c4ca096900dbbef98904c"},"previous_names":["microstates/microstates.js"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thefrontside%2Fmicrostates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thefrontside%2Fmicrostates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thefrontside%2Fmicrostates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thefrontside%2Fmicrostates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thefrontside","download_url":"https://codeload.github.com/thefrontside/microstates/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254292042,"owners_count":22046426,"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":["batch-transitions","composition","lens","microstates","state-machines","transition"],"created_at":"2024-07-31T07:01:13.915Z","updated_at":"2025-05-15T07:06:15.487Z","avatar_url":"https://github.com/thefrontside.png","language":"JavaScript","readme":"[![npm](https://img.shields.io/npm/v/microstates.svg)](https://www.npmjs.com/package/microstates)\n[![bundle size (minified + gzip)](https://badgen.net/bundlephobia/minzip/microstates)](https://bundlephobia.com/result?p=microstates)\n[![Build Status](https://circleci.com/gh/thefrontside/microstates/tree/master.svg?style=shield)](https://circleci.com/gh/thefrontside/microstates/tree/master)\n[![Coverage Status](https://coveralls.io/repos/github/thefrontside/microstates/badge.svg?branch=master)](https://coveralls.io/github/thefrontside/microstates?branch=master)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Chat on Discord](https://img.shields.io/discord/700803887132704931?Label=Discord)](https://discord.gg/GhREy5v)\n[![Created by The Frontside](https://img.shields.io/badge/created%20by-frontside-26abe8.svg)](https://frontside.com)\n\n\u003ch1\u003e\n  \u003cimg src=\"./packages/microstates/README/microstates-logo.svg\" alt=\"Microstates Logo\" width=\"200\" /\u003e\u003cbr\u003eMicrostates\n\u003c/h1\u003e\n\nMicrostates makes working with pure functions over immutable data\nfeel like working with the classic, mutable models we all know and love.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eTable of Contents\u003c/strong\u003e\u003c/summary\u003e\n\u003c!-- toc --\u003e\n\n- [Features](#features)\n- [Why Microstates?](#why-microstates)\n  - [M in MVC](#m-in-mvc)\n  - [Functional Models](#functional-models)\n- [What is a Microstate?](#what-is-a-microstate)\n- [Types and Type Composition](#types-and-type-composition)\n  - [Creating your own microstates](#creating-your-own-microstates)\n  - [Array Microstates](#array-microstates)\n  - [Object Microstates](#object-microstates)\n- [Transitions](#transitions)\n  - [Transitions for built-in types](#transitions-for-built-in-types)\n  - [Type transitions](#type-transitions)\n  - [Chaining transitions](#chaining-transitions)\n  - [The `initialize` transition](#the-initialize-transition)\n  - [The `set` transition](#the-set-transition)\n  - [Transition scope](#transition-scope)\n- [State Machines](#state-machines)\n  - [Explicit Transitions](#explicit-transitions)\n  - [Transition methods](#transition-methods)\n  - [Immutable Object vs Immutable Data Structure](#immutable-object-vs-immutable-data-structure)\n- [Framework Integrations](#framework-integrations)\n- [`microstates` npm package](#microstates-npm-package)\n  - [create(Type, value): Microstate](#createtype-value-microstate)\n  - [from(any): Microstate](#fromany-microstate)\n  - [map(microstate, fn): Microstate](#mapmicrostate-fn-microstate)\n- [Streaming State](#streaming-state)\n  - [Structural Sharing](#structural-sharing)\n  - [Memoized Getters](#memoized-getters)\n  - [Debounce no-op transitions](#debounce-no-op-transitions)\n  - [Identity Constructors](#identity-constructors)\n    - [Store(microstate, callback)](#storemicrostate-callback)\n    - [Observable.from(microstate)](#observablefrommicrostate)\n- [The Vision of Microstates](#the-vision-of-microstates)\n  - [Shared Solutions](#shared-solutions)\n  - [Added Flexibility](#added-flexibility)\n  - [Framework Agnostic Solutions](#framework-agnostic-solutions)\n- [FAQ](#faq)\n  - [What if I can't use class syntax?](#what-if-i-cant-use-class-syntax)\n  - [What if I can't use Class Properties?](#what-if-i-cant-use-class-properties)\n- [Run Tests](#run-tests)\n\n\u003c!-- tocstop --\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e🎬 \u003cstrong\u003eVideos\u003c/strong\u003e\u003c/summary\u003e\n\n  - [Building a shopping cart with Microstates.js](https://www.youtube.com/watch?v=N9iu8h0CzNY) - The Frontside YouTube - Taras Mankovski \u0026 Alex Regan\n  - [State of Enjoyment](https://www.youtube.com/watch?v=zWEg4-bGot0) at Framework Summit 2018 - Charles Lowell\n  - [Microstates: The Ember component of state management](https://www.youtube.com/watch?v=kt5aRmhaE2M\u0026t=7s) at EmberATX\n  - [Composable State Primitives for JavaScript with Charles Lowell \u0026 Taras Mankovski](https://www.youtube.com/watch?v=4dmcZrUdKx4) - Devchat.tv\n  -  [Composable State Management with Microstates.js](https://www.youtube.com/watch?v=g0-nf7m1Muo\u0026t=1s) at Toronto.js - Taras Mankovski\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e💬 \u003cstrong\u003eChat\u003c/strong\u003e\u003c/summary\u003e\n\n  [Join our community on Discord](https://discord.gg/GhREy5v). Everyone is welcome. If you're a new to programming join our #beginner channel where extra care is taken to support those who're just getting started.\n\n\u003c/details\u003e\n\n# Features\n\nWith Microstates added to your project, you get:\n\n- 🍇 Composable type system\n- 🍱 Reusable state atoms\n- 💎 Pure immutable state transitions without writing reducers\n- ⚡️ Lazy and synchronous out of the box\n- 🦋 Most elegant way to express state machines\n- 🎯 Transpilation free type system\n- 🔭 Optional integration with Observables\n- ⚛ Use in Node.js, browser or React Native\n- 🔬 [It's tiny](https://bundlephobia.com/result?p=microstates)\n\nBut, most importantly, Microstates makes working with state fun.\n\n**When was the last time you had fun working with state?**\n\nFor many, the answer is probably never, because state management in JavaScript is an endless game of compromises. You can choose to go fully immutable and write endless reducers. You can go mutable and everything becomes an observable. Or you can `setState` and lose the benefits of serialization and time travel debugging.\n\nUnlike the view layer, where most frameworks agree on some variation of React's concept of components, none of the current crop of state management tools strike the same balance that React components introduced to the API.\n\nReact components have a tiny API. They are functional, simple and extremely reusable. The tiny API gives you high productivity for little necessary knowledge. Functional components are predictable and easy to reason about. They are conceptually simple, but simplicity hides an underlying architecture geared for performance. Their simplicity, predictability and isolation makes them composable and reusable.\n\nThese factors combined are what make React style components easy to work with and ultimately fun to write. A Tiny API abstracting a sophisticated architecture that delivers performance and is equally useful on small and big projects is the outcome that we set out to achieve for state management with Microstates.\n\nIt's not easy to find the right balance between simplicity and power, but considering the importance of state management in web applications, we believe it's a worthy challenge. Checkout the [Vision of Microstates](#the-vision-of-microstates) section if you're interested in learning more about where we're going.\n\n\u003c!--\n# Why Microstates?\n\nOur tools affect how we solve problems and collaborate.\n\nTwo tools can serve the same purpose but foster completely different ecosystems. Take jQuery plugins and React components as examples. Both of these tools provided a way to add custom behaviour to a DOM element but they fostered very different communities.\n\nIn the React world today, we see many special purpose components that are easily combined to create sophisticated user experiences. These components tend to have few options but provide just the right API for you to build what you need.\n\njQuery plugins, on the other hand, offer endsless lists of options that are difficult get just right. In the jQuery ecosystem, libraries tend to be monolithic because plugins from different libraries often do not work well together.\n\nAs a result, in the React ecosystem we see components like [react-virtualized](https://github.com/bvaughn/react-virtualized) and [react-dnd](https://github.com/react-dnd/react-dnd) that are made by experienced React developers. These components save companies and developers millions of dollars in wasted development by eliminating the need for everyone to re-invent these components to build their user experiences.\n\nThe ability to leverage the experience of other developers in the form of published packages elevates our entire ecosystem. We call this _standing on the shoulders of giants_. Our goal is to bring this level of collaboration to state management.\n\n## M in MVC\n\nIf you're a web developer and are using a framework, you might be wondering how Microstates will work within said framework. For now, I will say that we'll have an integration for each framework, but it's important that we're on the same page about the role of Microstates within your application. Once we have that, you'll see more ways to use Microstates than I can cover in this README.\n\nRegardless of the kind of application you're building, your application is made of code that roughly represents data, converts user input into data and presents data to the user. This traditionally has been described as MVC pattern where M, model, is data that is persisted or accumulated through user actions or input. V, view, is how that data is presented to the user, often we describe with components and C, controller, which represents the constraints that exist on the user's actions.\n\nTalking about MVC is a little passé in some communities, and understandbly so. Traditional MVC did not bring a lot of comfort to early adopters of web frameworks. Of the early adopters, only a few MVCish frameworks are left, but regardless of the popularity of the term, the architectural pattern is still a big part of our applications.\n\n\nWhat we're seeing now is the discovery of what MVC looks like in modern web applications. One thing that most of us can agree on is that our views are now called components. Over the last 5 years, we saw a lot of competition in the view layer to make the most performant and ergonomic view building developer experience.\n\n## Functional Models\n\nThe view boom was in big part ignited by the introduction of React. With React, came the introduction and mass adoption of functional programming ideas in the JavaScript ecosystem. Functional thinking brought a lot of simplicity to the view layer. It is conceptually simple - a component is a function that takes props and returns DOM. This simplicity helped developers learn React and has been adopted to a varied degree by most frameworks. The API that each frameworks exposes to their view is somewhat different but the general idea is the same.\n\nMicrostates brings the same kind of simplicity to the model layer. A Microstate is a functional model in a way that a component is a functional view. A component takes props and returns DOM; a Microstate takes value and returns state. DOM is a tree of element instances, state is a tree of model instances. A DOM tree is created by passing data to a root component. A state tree is created from a root type and value. A component is an abstraction that we use to manipulate the DOM tree. A microstate is an abstraction that we use to manipulate the state tree.\n\nWhen you want to change what the user sees, you could imperatively manipulate the DOM elements with jQuery, but React taught us to change DOM declaratively by changing the data that the DOM reflects. In the same way, when you want to change the state, you must change the value and allow the state to be reflected. --\u003e\n\n# What is a Microstate?\n\nA Microstate is just an object that is created from a value and a type. The value is just data, and the type is what defines how you can transition that data from one form into the next. Unlike normal JavaScript objects, microstates are 100% immutable and cannot be changed. They can only derive new immutable microstates through one of their type's transitions.\n\n# Types and Type Composition\n\nMicrostates comes out of the box with 5 primitive types: `Boolean`, `Number`, `String`, `Object` and `Array`.\n\n```js\nimport { create, valueOf } from 'microstates';\n\nlet meaningOfLifeAndEverything = create(Number, 42);\nconsole.log(meaningOfLifeAndEverything.state);\n//\u003e 42\n\nlet greeting = create(String, 'Hello World');\nconsole.log(greeting.state);\n//\u003e Hello World\n\nlet isOpen = create(Boolean, true);\nconsole.log(isOpen.state);\n//\u003e true\n\n// For Object and Array use microstates valueOf method\nlet foo = create(Object, { foo: 'bar' });\nconsole.log(valueOf(foo));\n//\u003e { foo: 'bar' }\n\nlet numbers = create(Array, [1, 2, 3, 4]);\nconsole.log(valueOf(numbers));\n//\u003e [ 1, 2, 3, 4 ]\n```\n\nApart from these basic types, every other type in Microstates is built by combining other types. So for example, to create a Person type you could define a JavaScript class with two properties: `name` which has type String and `age` which has type Number.\n\n```js\nclass Person {\n  name = String;\n  age = Number;\n}\n```\n\nOnce you have a type, you can use that type to create as many people as your application requires:\n\n```js\nimport { create } from 'microstates';\n\nlet person = create(Person, { name: 'Homer', age: 39 });\n```\n\nEvery microstate created with a type of `Person` will be an object\nextending Person to have a `set()` method:\n\n```txt\n+----------------------+\n|                      |       +--------------------+\n|  Microstate\u003cPerson\u003e  +-name--+                    +-concat()-\u003e\n|                      |       | Microstate\u003cString\u003e +-set()-\u003e\n|                      |       |                    +-state: 'Homer'\n|                      |       +--------------------+\n|                      |\n|                      |       +--------------------+\n|                      +-age---+                    +-increment()-\u003e\n|                      |       | Microstate\u003cNumber\u003e +-decrement()-\u003e\n|                      |       |                    +-set()-\u003e\n|                      |       |                    +-state: 39\n|                      |       +--------------------+\n|                      |\n|                      +-set()-\u003e\n|                      |\n+----------------------+\n```\n\nFor the five built in types, Microstates automatically gives you transitions that you can use to change their value. You don't have to write any code to handle common operations.\n\n## Creating your own microstates\n\nTypes can be combined with other types freely and Microstates will take care of handling the transitions for you. This makes it possible to build complex data structures that accurately describe your domain.\n\nLet's define another type that uses the person type.\n\n```js\nclass Car {\n  designer = Person;\n  name = String;\n}\n\nlet theHomerCar = create(Car, {\n  designer: { name: 'Homer', age: 39 },\n  name: 'The Homer'\n});\n```\n\n`theHomerCar` object will have the following shape,\n\n```txt\n+-------------------+           +----------------------+\n|                   |           |                      |       +--------------------+\n|  Microstate\u003cCar\u003e  |           |  Microstate\u003cPerson\u003e  +-name--+                    +-concat()-\u003e\n|                   |           |                      |       | Microstate\u003cString\u003e +-set()-\u003e\n|                   +-designer--+                      |       |                    +-state: 'Homer'\n|                   |           |                      |       +--------------------+\n|                   |           |                      |\n|                   |           |                      |       +--------------------+\n|                   |           |                      +-age---+                    +-increment()-\u003e\n|                   |           |                      |       | Microstate\u003cNumber\u003e +-decrement()-\u003e\n|                   |           |                      |       |                    +-set()-\u003e\n|                   |           |                      |       |                    +-state: 39\n|                   |           |                      |       +--------------------+\n|                   |           |                      |\n|                   |           |                      +-set()-\u003e\n|                   |           |                      |\n|                   |           +----------------------+\n|                   |\n|                   |           +--------------------+\n|                   +-name------+                    +-concat()-\u003e\n|                   |           | Microstate\u003cString\u003e +-set()-\u003e\n|                   |           |                    +-state: 'The Homer'\n|                   |           +--------------------+\n|                   |\n|                   +-set()-\u003e\n|                   |\n+-------------------+\n```\n\nYou can use the object dot notation to access sub microstates. Using the same example from above:\n\n```js\ntheHomerCar.designer;\n//\u003e Microstate\u003cPerson\u003e{ name: Microstate\u003cString\u003e'Homer', age: Microstate\u003cNumber\u003e39 }\n\ntheHomerCar.designer.age.state;\n//\u003e 39\n\ntheHomerCar.name.state;\n//\u003e The Homer\n```\n\nYou can use the `valueOf()` function available from the microstates\nmodule to retrieve the underlying value represented by a microstate.\n\n```js\nimport { valueOf } from 'microstates';\n\nvalueOf(theHomerCar);\n//\u003e { designer: { name: 'Homer', age: 39 }, name: 'The Homer' }\n```\n\n## Array Microstates\n\nQuite often it is helpful to describe your data as a collection of types. For example, a blog might have an array of posts. To do this, you can use the array of type notation `[Post]`. This signals that Microstates of this type represent an array whose members are each of the `Post` type.\n\n```js\nclass Blog {\n  posts = [Post];\n}\n\nclass Post {\n  id = Number;\n  title = String;\n}\n\nlet blog = create(Blog, {\n  posts: [\n    { id: 1, title: 'Hello World' },\n    { id: 2, title: 'Most fascinating blog in the world' }\n  ]\n});\n\nfor (let post of blog.posts) {\n  console.log(post);\n}\n//\u003e Microstate\u003cPost\u003e{ id: 1, title: 'Hello World' }\n//\u003e Microstate\u003cPost\u003e{ id: 2, title: 'Most fascinating blog in the world' }\n```\n\nWhen you're working with an array microstate, the shape of the Microstate is determined by the value. In this case, `posts` is created with two items which will, in turn, create a Microstate with two items. Each item will be a Microstate of type `Post`. If you push another item onto the `posts` Microstate, it'll be treated as a `Post`.\n\n```js\nlet blog2 = blog.posts.push({ id: 3, title: 'It is only getter better' });\n\nfor (let post of blog2.posts) {\n  console.log(post);\n}\n\n//\u003e Microstate\u003cPost\u003e{ id: 1, title: 'Hello World' }\n//\u003e Microstate\u003cPost\u003e{ id: 2, title: 'Most fascinating blog in the world' }\n//\u003e Microstate\u003cPost\u003e{ id: 3, title: 'It is only getter better' }\n```\n\nNotice how we didn't have to do any extra work to define the state\ntransition of adding another post to the list? That's the power of\ncomposition!\n\n## Object Microstates\n\nYou can also create an object microstate with `{Post}`. The difference is that the collection is treated as an object. This can be helpful when creating normalized data stores.\n\n```js\nclass Blog {\n  posts = { Post };\n}\n\nclass Post {\n  id = Number;\n  title = String;\n}\n\nlet blog = create(Blog, {\n  posts: {\n    '1': { id: 1, title: 'Hello World' },\n    '2': { id: 2, title: 'Most fascinating blog in the world' }\n  }\n});\n\nblog.posts.entries['1'];\n//\u003e Microstate\u003cPost\u003e{ id: 1, title: 'Hello World' }\n\nblog.posts.entries['2'];\n//\u003e Microstate\u003cPost\u003e{ id: 2, title: 'Most fascinating blog in the world' }\n```\n\nObject type microstates have `Object` transitions, such as `assign`, `put` and `delete`.\n\n```js\nlet blog2 = blog.posts.put('3', { id: 3, title: 'It is only getter better' });\n\nblog2.posts.entries['3'];\n//\u003e Microstate\u003cPost\u003e{ id: 3, title: 'It is only getter better' }\n```\n\n# Transitions\n\nTransitions are the operations that let you derive a new state from an existing state. All transitions return another Microstate. You can use state charts to visualize microstates. For example, the `Boolean` type can be described with the following statechart.\n\n\u003cimg src=\"README/boolean-statechart.png\" alt=\"Boolean Statechart\" width=\"500\" /\u003e\n\nThe `Boolean` type has a `toggle` transition which takes no arguments and creates a new microstate with the state that is opposite of the current state.\n\nHere is what this looks like with Microstates.\n\n```js\nimport { create } from 'microstates';\n\nlet bool = create(Boolean, false);\n\nbool.state;\n//\u003e false\n\nlet inverse = bool.toggle();\n\ninverse.state;\n//\u003e true\n```\n\n\u003e _Pro tip_ Remember, Microstate transitions always return a Microstate. This is true both inside and outside the transition function. Using this convention can allow composition to reach crazy levels of complexity.\n\nLet's use a `Boolean` in another type and see what happens.\n\n```js\nclass App {\n  name = String;\n  notification = Modal;\n}\n\nclass Modal {\n  text = String;\n  isOpen = Boolean;\n}\n\nlet app = create(App, {\n  name: 'Welcome to your app',\n  notification: {\n    text: 'Hello there',\n    isOpen: false\n  }\n});\n\nlet opened = app.notification.isOpen.toggle();\n//\u003e Microstate\u003cApp\u003e\n\nvalueOf(opened);\n//\u003e {\n// name: 'Welcome to your app',\n// notification: {\n//   text: 'Hello there',\n//   isOpen: true\n// }}\n```\n\nMicrostate transitions always return the whole object. Notice how we invoked the boolean transition `app.notification.isOpen`, but we didn't get a new Boolean microstate? Instead, we got a completely new App where everything was the same except for that single toggled value.\n\n## Transitions for built-in types\n\nThe primitive types have predefined transitions:\n\n- `Boolean`\n  - `toggle(): Microstate` - return a Microstate with opposite boolean value\n- `String`\n  - `concat(str: String): Microstate` - return a Microstate with `str` added to the end of the current value\n- `Number`\n  - `increment(step = 1: Number): Microstate` - return a Microstate with number increased by `step`, default is 1.\n  - `decrement(step = 1: Number): Microstate` - return a Microstate with number decreased by `step`, default is 1.\n- `Object`\n  - `assign(object): Microstate` - return a Microstate after merging object into current object.\n  - `put(key: String, value: Any): Microstate` - return a Microstate after adding value at given key.\n  - `delete(key: String): Microstate` - return a Microstate after removing property at given key.\n- `Array`\n  - `map(fn: (Microstate) =\u003e Microstate): Microstate` - return a Microstate with mapping function applied to each element in the array. For each element, the mapping function will receive the microstate for that element. Any transitions performed in the mapping function will be included in the final result.\n  - `push(value: any): Microstate` - return a Microstate with value added to the end of the array.\n  - `pop(): Microstate` - return a Microstate with last element removed from the array.\n  - `shift(): Microstate` - return a Microstate with element removed from the array.\n  - `unshift(value: any): Microstate` - return a Microstate with value added to the beginning of the array.\n  - `filter(fn: state =\u003e boolean): Microstate` - return a Microstate with filtered array. The predicate function will receive state of each element in the array. If you return a falsy value from the predicate, the item will be excluded from the returned microstate.\n  - `clear(): Microstate` - return a microstate with an empty array.\n\nMany transitions on primitive types are similar to methods on original classes. The biggest difference is that transitions always return Microstates.\n\n## Type transitions\n\nDefine the transitions for your types using methods. Inside of a transition, you can invoke any transitions you like on sub microstates.\n\n```js\nimport { create } from 'microstates';\n\nclass Person {\n  name = String;\n  age = Number;\n\n  changeName(name) {\n    return this.name.set(name);\n  }\n}\n\nlet homer = create(Person, { name: 'Homer', age: 39 });\n\nlet lisa = homer.changeName('Lisa');\n```\n\n## Chaining transitions\n\nTransitions can be composed out of any number of subtransitions. This is often referred to as \"batch transitions\" or \"transactions\". Let's say that when we authenticate a session, we need to both store the token and indicate that the user is now authenticated. To do this, we can chain transitions. The result of the last operation will become a new microstate.\n\n```js\nclass Session {\n  token = String;\n}\n\nclass Authentication {\n  session = Session;\n  isAuthenticated = Boolean;\n\n  authenticate(token) {\n    return this.session.token.set(token).isAuthenticated.set(true);\n  }\n}\n\nclass App {\n  authentication = Authentication;\n}\n\nlet app = create(App, { authentication: {} });\n\nlet authenticated = app.authentication.authenticate('SECRET');\n\nvalueOf(authenticated);\n//\u003e { authentication: { session: { token: 'SECRET' }, isAuthenticated: true } }\n```\n\n## The `initialize` transition\n\nJust as every state machine must begin life in its \"start state\", so too must every microstate begin life in the right state. For those cases where the start state depends on some logic, there is the `initialize` transition. The `initialize` transition is just like any other transition, except that it will be automatically called within create on every Microstate that declares one.\n\nYou can even use this mechanism to transition the microstate to one with a completely different type and value.\n\nFor example:\n\n```js\nclass Person {\n  firstName = String;\n  lastName = String;\n\n  initialize({ firstname, lastname } = {}) {\n    let initialized = this;\n\n    if (firstname) {\n      initialized = initialized.firstName.set(firstname);\n    }\n\n    if (lastname) {\n      initialized = initialized.lastName.set(lastname);\n    }\n\n    return initialized;\n  }\n}\n```\n\n## The `set` transition\n\nThe `set` transition is the only transition that is available on all types. It can be used to replace the value of the current Microstate with another value.\n\n```js\nimport { create } from 'microstates';\n\nlet number = create(Number, 42).set(43);\n\nnumber.state;\n//\u003e 43\n```\n\n\u003c!--\n\nYou can also use the `set` transition to replace the current Microstate with another Microstate. This is especially useful when building state machines because it allows you to change the type of the current Microstate. By changing the type, you're also changing available transitions and how the state is calculated.\n\n```js\nclass Vehicle {\n  weight = Number;\n  towing = Vehicle;\n\n  get isTowing() {\n    return !!this.towing;\n  }\n\n  get towCapacity() {\n    throw new Error('not implemented');\n  }\n\n  tow() {\n    throw new Error('not implemented');\n  }\n}\n\nclass Car extends Vehicle {}\n\nclass Truck extends Vehicle {\n  towCapacity = Number;\n\n  tow(vehicle) {\n    if (vehicle.weight.state \u003c this.towCapacity.state) {\n      return this.towing.set(vehicle);\n    } else {\n      throw new Error(`Unable to tow ${vehicle.weight.state} because it exceeds tow capacity of ${this.towCapacity.state}`);\n    }\n  }\n}\n\nclass Friend {\n  vehicle = Vehicle;\n}\n\nlet prius = create(Car, { weight: 3000 });\n\nlet mustang = create(Car, { weight: 3500, towCapacity: 1000 });\nlet f150 = create(Truck, { weight: 5000, towCapacity: 13000 });\n\nlet rob = create(Friend).vehicle.set(mustang);\nlet charles = create(Friend).vehicle.set(f150);\n\nrob.vehicle.tow(prius);\n//\u003e Error: not implemented\n\nlet result = charles.vehicle.tow(prius)\n\nresult.vehicle.state.isTowing\n//\u003e true\n```\n\n--\u003e\n\n\u003e _Pro tip_: Microstates will never require you to understand Monads in order to use transitions, but if you're interested in learning about the primitives of functional programming that power Microstates, you may want to checkout [funcadelic.js](https://github.com/cowboyd/funcadelic.js).\n\n## Transition scope\n\nMicrostates are composable, and they work exactly the same no matter what other microstate they're a part of. For this reason, Microstate transitions only have access to their own transitions and the transitions of the microstates they contain. What they do _not_ have is access to their context. This is similar to how components work. The parent component can render children and pass data to them, but the child components do not have direct access to the parent component. The same principle applies in Microstates, so as a result, it benefits from the same advantages of isolation and composability that make components awesome.\n\n# State Machines\n\nA state machine is a system that has a predefined set of states. At any given point, the state machine can only be in one of these states. Each state has a predefined set of transitions that can be derived from that state. These constraints are beneficial to application architecture because they provide a way to identify application state and suggest how the application state can change.\n\nFrom its conception, Microstates was created to be the most convenient way to express state machines. The goal was to design an API that would eliminate the barrier of using state machines and allow for them to be composable. After almost two years of refinement, the result is an API that has evolved significantly beyond what we typically associate with code that expresses state machines.\n\n[xstate](https://github.com/davidkpiano/xstate) for example, is a great specimen of the classic state machine API. It's a fantastic library and it addresses the very real need for state machines and statecharts in modern applications. For purposes of contrast, we'll use it to illustrate the API choices that went into Microstates.\n\n## Explicit Transitions\n\nMost state machine libraries focus on finding the next state given a configuration. For example, this [xstate](https://github.com/davidkpiano/xstate#finite-state-machines) declaration describes what state id to match when in a specific state.\n\n```js\nimport { Machine } from 'xstate';\n\nconst lightMachine = Machine({\n  key: 'light',\n  initial: 'green',\n  states: {\n    green: {\n      on: {\n        TIMER: 'yellow'\n      }\n    },\n    yellow: {\n      on: {\n        TIMER: 'red'\n      }\n    },\n    red: {\n      on: {\n        TIMER: 'green'\n      }\n    }\n  }\n});\n```\n\nMicrostates does not do any special state resolution. You explicitly declare what happens on a state transition. Here is what a similar state machine looks like in Microstates.\n\n```js\nclass LightMachine {\n  color = String;\n\n  initialize({ color = 'green' } = {}) {\n    return this.color.set(color);\n  }\n\n  timer() {\n    switch (this.color.state) {\n      case 'green': return this.color.set('yellow');\n      case 'yellow': return this.color.set('red');\n      case 'red':\n      default:\n        return this.color.set('green');\n    }\n  }\n}\n```\n\nWith Microstates, you explicitly describe what happens on transition and define the matching mechanism.\n\n## Transition methods\n\n`transitionTo` is often used by state machine libraries to trigger state transition. Here is an example with xstate library,\n\n```js\nconst nextState = lightMachine.transition('green', 'TIMER').value;\n\n//\u003e 'yellow'\n```\n\nMicrostates does not have such a method. Instead, it relies on vanilla JavaScript property lookup. The method invocation is equivalent to calling `transitionTo` with name of the transition.\n\n```js\nimport { create } from 'microstates';\n\nlet lightMachine = create(LightMachine);\n\nconst nextState = lightMachine.timer();\n\nnextState.color.state;\n//\u003e 'yellow'\n```\n\n## Immutable Object vs Immutable Data Structure\n\nWhen you create a state machine with xstate, you create an immutable object. When you invoke a transition on an `xstate` state machine, the value of the object is the ID of the next state. All of the concerns of immutable value change as a result of state change are left for you to handle manually.\n\nMicrostates treats value as part of the state machine. It allows you to colocate your state transitions with reducers that change the value of the state.\n\n# Framework Integrations\n\n- [React.js](https://github.com/microstates/react)\n- [Ember.js](https://github.com/microstates/ember)\n- Create a PR if you created an integration that you'd like to add to this list.\n- Create an issue if you'd like help integrating Microstates with a framework\n\n# `microstates` npm package\n\nThe `microstates` package provides the `Microstate` class and functions that operate on Microstate objects.\n\nYou can import the `microstates` package using:\n\n```bash\nnpm install microstates\n\n# or\n\nyarn add microstates\n```\n\nThen import the libraries using:\n\n```js\nimport Microstate, { create, from, map } from 'microstates';\n```\n\n## create(Type, value): Microstate\n\nThe `create` function is conceptually similar to `Object.create`. It creates a Microstate object from a type class and a value. This function is lazy, so it should be safe in most high performant operations even with complex and deeply nested data structures.\n\n```js\nimport { create } from 'microstates';\n\ncreate(Number, 42);\n//\u003e Microstate\n```\n\n## from(any): Microstate\n\n`from` allows the conversion of any POJO (plain JavaScript object) into a Microstate. Once you've created a Microstate, you can perform operations on all properties of the value.\n\n```js\nimport { from } from 'microstates';\n\nfrom('hello world');\n//Microstate\u003cString\u003e\n\nfrom(42).increment();\n//\u003e Microstate\u003cNumber\u003e\n\nfrom(true).toggle();\n//\u003e Microstate\u003cBoolean\u003e\n\nfrom([1, 2, 3]);\n//\u003e Microstate\u003cArray\u003cNumber\u003e\u003e\n\nfrom({ hello: 'world' });\n//\u003e Microstate\u003cObject\u003e\n```\n\n`from` is lazy, so you can consume any deeply nested POJO and\nMicrostates will allow you to perform transitions with it. The cost of\nbuilding the objects inside of Microstates is paid whenever you reach\nfor a Microstate inside. For example, `let o = from({ a: { b: { c: 42\n}}})` doesn't do anything until you start to read the properties with\ndot notiation like `o.entries` or with iteration / destructuring.\n\n```js\nlet [[[[[[c]]]]]] = from({a: { b: {c: 42}}});\nvalueOf(c.increment());\n\n// { a: { b: { c: 43 }}}\n\nlet greeting = from({ hello: ['world']});\nlet [ world ] = greeting.entries.hello;\nvalueOf(world.concat('!!!'));\n// { hello: [ 'world!!!' ]}\n```\n\n## map(microstate, fn): Microstate\n\nThe `map` function invokes the function for each microstate in an array microstate. It is usually used to map over an array of microstates and return an array of components. The mapping function will receive each microstate in the array. You can invoke transitions on each microstate as you would usually.\n\n```js\nlet numbers = create([Number], [1, 2, 3, 4]);\n\n\u003cul\u003e\n  {map(numbers, number =\u003e (\n    \u003cli onClick={() =\u003e number.increment()}\u003e{number.state}\u003c/li\u003e\n  ))}\n\u003c/ul\u003e;\n```\n\n# Streaming State\n\nA microstate represents a single immutable value with transitions to derive the next value. Microstates provides a mechanism called Identity that allows to emit stream of Microstates. When you create an Identity from a Microstate, you get an object that has the same shape the original microstate. Every composed microstate becomes an identity and every transition gets wrapped in side effect emitting behaviour specific to the identity's constructor. Identity wrapped Microstate offer the following benefits over raw Microstates.\n\n## Structural Sharing\n\nA common performance optimization used by all reactive engines is to prevent re-renders for components who’s props have not changed. The most efficient way to determine if a value has not changed it to perform an exact equality check, for example: `prevValue === currentValue`. If the reference is the same, then consider the value unchanged. The Identity makes this possible with Microstates by internally managing how the Identity is constructed as a result of a transition. It will automatically determine which branches of microstates are unchanged and reuse previous identities for those branches.\n\n## Memoized Getters\n\nMicrostates are immutable which makes it safe for us to memoize computations that are derived off their state. Identies will automatically memoize getters and return previously computed value when the microstate backing the identity has not changed. When a transition is invoked on the identity, the part of the identity tree that are changed will be re-created effectively invalidating the cache for the changed parts of the identity. The getters will be recomputed for state that is changed.\n\n## Debounce no-op transitions\n\nIdentities automatically prevent unnecessary re-renders by debouncing transitions that do not change the value. This eliminates the need for `shouldComponentUpdate` hooks for pure components because it is safe to assume that a component that is re-rendering is re-rendering as a result of a transition that changed the value. In other words, if the current state and the state being transitioned to are the same, then a \"new state\" that would be the same is not emitted.\n\n```js\nlet id = Store(from({ name: 'Charles' }), next =\u003e {\n  console.count('changed');\n  id = next;\n});\n\nid.name.set('Charles');\nid.name.set('Charles');\n```\n\nThe above transitions would be debounced because they do not change the value. The update callback would not be called, even though set operation is called twice.\n\n## Identity Constructors\n\nMicrostates comes with two Identity constructors: _Store_ and _Observable_. Store will send next identity to a callback. Observable will create a stream of identities and send next identity through the stream.\n\n### Store(microstate, callback)\n\nStore identity constructor takes two arguments: microstate and a callback. It returns an identity. When a transition is invoked on the identity, the callback will receive the next identity.\n\n```js\nimport { Store, from, valueOf } from 'microstates';\n\nlet initial = create(Number, 42);\n\nlet last;\n\nlast = Store(initial, next =\u003e (last = next));\n\nlast.increment();\n//\u003e undefined\n// callback will be invoked syncronously on transition\n\n// last here will reference the last\nlast.increment();\n//\u003e undefined\n\nvalueOf(last);\n//\u003e 44\n```\n\nThe same mechanism can be used with React or any other reactive environment.\n\n```js\nimport React from 'react';\nimport { Store, create } from 'microstates';\n\nclass Counter extends React.Component {\n  state = {\n    last: Store(create(Number, 42), next =\u003e this.setState({ last: next }))\n  };\n  render() {\n    let { last } = this.state;\n    return (\n      \u003cbutton onClick={() =\u003e last.increment()}\u003eIncrement {last.state}\u003c/button\u003e\n    );\n  }\n}\n```\n\n### Observable.from(microstate)\n\nMicrostates provides an easy way to convert a Microstate which represents a single value into a Observable stream of values. This is done by passing a Microstate to Observable.from function. This function will return a Observable object with a subscribe method. You can subscribe to the stream by passing an observer to the subscribe function. Once you subscribe, you will synchronously receive a microstate with middleware installed that will cause the result of transitions to be pushed through the stream.\n\nYou should be able to use to any implementation of Observables that supports Observer.from using symbol-observable. We'll use RxJS for our example.\n\n```js\nimport { from as observableFrom } from 'rxjs';\nimport { create } from 'microstates';\n\nlet homer = create(Person, { firstName: 'Homer', lastName: 'Simpson' });\n\nlet observable = observableFrom(homer);\n\nlet last;\nlet subscription = observable.subscribe(next =\u003e {\n  // capture the next microstate coming through the stream\n  last = next;\n});\n\nlast.firstName.set('Homer J');\n\nvalueOf(last);\n//\u003e { firstName: 'Homer J', lastName: 'Simpson' }\n```\n\n# The Vision of Microstates\n\nWhat if switching frameworks were easy? What if a company could build domain specific code that worked across frameworks? Imagine what it would be like if your tools stayed with you as you progressed in your career as an engineer. This is the world that we hope to create with Microstates.\n\n## Shared Solutions\n\nImagine never having to write another normalized data store again because someone made a normalized data store Microstate that you can compose into your app's Microstate.\n\nIn the future (not currently implemented), you will be able to write a normalized data store like this,\n\n```js\nimport Normalized from 'future-normalized-microstate';\n\nclass MyApp {\n  store = Normalized.of(Product, User, Category);\n}\n```\n\nThe knowledge about building normalized data stores is available in libraries like [Ember Data](https://github.com/emberjs/data), [Orbit.js](https://github.com/orbitjs/orbit), [Apollo](https://www.apollographql.com) and [urql](https://github.com/FormidableLabs/urql), yet many companies end up rolling their own because these tools are coupled to other stacks.\n\nAs time and resources permit, we hope to create a solution that will be flexible enough for use in most applications. If you're interested in helping us with this, please reach out.\n\n## Added Flexibility\n\nImagine if your favourite Calendar component came with a Microstate that allowed you to customize the logic of the calendar without touching the rendered output. It might looks something like this,\n\n```js\nimport Calendar from 'awesome-calendar';\nimport { filter } from 'microstates';\n\nclass MyCalendar extends Calendar.Model {\n  // make days as events\n  days = Day.of([Event]);\n\n  // component renders days from this property\n  get visibleDays() {\n    return filter(this.days, day =\u003e day.state.status !== 'finished');\n  }\n}\n\n\u003cCalendar.Component model={MyCalendar} /\u003e;\n```\n\nCurrently, this is pseudocode, but Microstates was architected to allow for these kinds of solutions.\n\n## Framework Agnostic Solutions\n\nCompetition moves our industry forward but consensus builds ecosystems.\n\nUnfortunately, when it comes to the M(odel) of the MVC pattern, we are seeing neither competition nor consensus. Every framework has its own model layer that is not compatible with others. This makes it difficult to create truly portable solutions that can be used on all frameworks.\n\nIt creates lock-in that is detrimental to the businesses that use these frameworks and to the developers who are forced to make career altering decisions before they fully understand their choices.\n\nWe don't expect everyone to agree that Microstates is the right solution, but we would like to start the conversation about what a shared primitive for state management in JavaScript might look like. Microstates is our proposal.\n\nIn many ways, Microstates is a beginning. We hope you'll join us for the ride and help us create a future where building stateful applications in JavaScript is much easier than it is today.\n\n# FAQ\n\n## What if I can't use class syntax?\n\nClasses are functions in JavaScript, so you should be able to use a function to do most of the same things as you would with classes.\n\n```js\nclass Person {\n  name = String;\n  age = Number;\n}\n```\n\n☝️ is equivalent to 👇\n\n```js\nfunction Person() {\n  this.name = String;\n  this.age = Number;\n}\n```\n\n## What if I can't use Class Properties?\n\nBabel compiles Class Properties into class constructors. If you can't use Class Properties, then you\ncan try the following.\n\n```js\nclass Person {\n  constructor() {\n    this.name = String;\n    this.age = Number;\n  }\n}\n\nclass Employee extends Person {\n  constructor() {\n    super();\n    this.boss = Person;\n  }\n}\n```\n\n# Run Tests\n\n```shell\n$ npm install\n$ npm test\n```\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthefrontside%2Fmicrostates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthefrontside%2Fmicrostates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthefrontside%2Fmicrostates/lists"}