{"id":15662490,"url":"https://github.com/skclusive/skclusive.mobx.observable","last_synced_at":"2026-02-13T03:16:12.316Z","repository":{"id":56192828,"uuid":"220669956","full_name":"skclusive/Skclusive.Mobx.Observable","owner":"skclusive","description":"Mobx port of C# language for Blazor","archived":false,"fork":false,"pushed_at":"2020-12-05T20:31:33.000Z","size":153,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-06T00:55:22.764Z","etag":null,"topics":["blazor","chsarp","dotnet-standard","mobx","mobx-observable"],"latest_commit_sha":null,"homepage":"","language":"C#","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/skclusive.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":"2019-11-09T16:26:19.000Z","updated_at":"2024-10-09T00:32:18.000Z","dependencies_parsed_at":"2022-08-15T14:20:57.299Z","dependency_job_id":null,"html_url":"https://github.com/skclusive/Skclusive.Mobx.Observable","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skclusive%2FSkclusive.Mobx.Observable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skclusive%2FSkclusive.Mobx.Observable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skclusive%2FSkclusive.Mobx.Observable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skclusive%2FSkclusive.Mobx.Observable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skclusive","download_url":"https://codeload.github.com/skclusive/Skclusive.Mobx.Observable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252601684,"owners_count":21774659,"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":["blazor","chsarp","dotnet-standard","mobx","mobx-observable"],"created_at":"2024-10-03T13:32:56.934Z","updated_at":"2026-02-13T03:16:12.280Z","avatar_url":"https://github.com/skclusive.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"Skclusive.Mobx.Observable\n=============================\n\n\u003c!--- using the https://github.com/mobxjs/mobx.dart/blob/master/README.md ---\u003e\n\nPort of [MobX](https://github.com/mobxjs/mobx) for the C# language.\n\n\u003e Supercharge the state-management in your Blazor apps with Transparent Functional Reactive Programming (TFRP)\n\n## Introduction\n\nMobX is a state-management library that makes it simple to connect the\nreactive data of your application with the UI. This wiring is completely automatic\nand feels very natural. As the application-developer, you focus purely on what reactive-data\nneeds to be consumed in the UI (and elsewhere) without worrying about keeping the two\nin sync.\n\nIt's not really magic but it does have some smarts around what is being consumed (**observables**)\nand where (**reactions**), and automatically tracks it for you. When the _observables_\nchange, all _reactions_ are re-run. What's interesting is that these reactions can be anything from a simple\nconsole log, a network call to re-rendering the UI.\n\n\u003e MobX has been a very effective library for the JavaScript\n\u003e apps and this port to the C# language aims to bring the same levels of productivity.\n\n\n## Core Concepts\n\nAt the heart of MobX are three important concepts: **Observables**, **Actions** and **Reactions**.\n\n### Observables\n\nObservables represent the reactive-state of your application. They can be simple scalars to complex object trees. By\ndefining the state of the application as a tree of observables, you can expose a _reactive-state-tree_ that the UI\n(or other observers in the app) consume.\n\nA simple reactive-counter is represented by the following observable:\n\n```c#\nusing Skclusive.Mobx.Observable;\n\nvar counter = ObservableValue\u003cint\u003e.From(0);\n```\n\nMore complex observables, such as classes, can be created as well.\n\n```C#\nusing Skclusive.Mobx.Observable;\n\npublic class Counter\n{\n    private readonly IObservableValue\u003cint\u003e _count = ObservableValue\u003cint\u003e.From(0);\n\n    public int Count\n    {\n        get =\u003e _count.Value;\n        set =\u003e _count.Value = value;\n    }\n\n    public void Increment()\n    {\n        _count.Value++;\n    }\n}\n```\n\n### Computed Observables\n\n\u003e What can be derived, should be derived. Automatically.\n\nThe state of your application consists of _**core-state**_ and _**derived-state**_. The _core-state_ is state inherent to the domain you are dealing with. For example, if you have a `Contact` entity, the `FirstName` and `LastName` form the _core-state_ of `Contact`. However, `FullName` is _derived-state_, obtained by combining `FirstName` and `LastName`.\n\nSuch _derived state_, that depends on _core-state_ or _other derived-state_ is called a **Computed Observable**. It is automatically kept in sync when its underlying observables change.\n\n\u003e State in MobX = Core-State + Derived-State\n\n```C#\nusing Skclusive.Mobx.Observable;\n\npublic class Contact\n{\n    private readonly IObservableValue\u003cstring\u003e _firstName;\n\n    private readonly IObservableValue\u003cstring\u003e _lastName;\n\n    private readonly IComputedValue\u003cstring\u003e _fullName;\n\n    public Contact()\n    {\n        _firstName = ObservableValue\u003cstring\u003e.From();\n\n        _lastName = ObservableValue\u003cstring\u003e.From();\n\n        _fullName = ComputedValue\u003cstring\u003e.From(() =\u003e $\"{FirstName}, {LastName}\");\n    }\n\n    public string FirstName\n    {\n        get =\u003e _firstName.Value;\n        set =\u003e _firstName.Value = value;\n    }\n\n    public string LastName\n    {\n        get =\u003e _lastName.Value;\n        set =\u003e _lastName.Value = value;\n    }\n\n    public string FullName =\u003e _fullName.Value;\n}\n```\n\nIn the example above **`FullName`** is automatically kept in sync if either `FirstName` and/or `LastName` changes.\n\n### Actions\n\nActions are how you mutate the observables. Rather than mutating them directly, actions\nadd a semantic meaning to the mutations. For example, instead of just doing `Value++`,\nfiring an `Increment()` action carries more meaning. Besides, actions also batch up\nall the notifications and ensure the changes are notified only after they complete.\nThus the observers are notified only upon the atomic completion of the action.\n\nNote that actions can also be nested, in which case the notifications go out\nwhen the top-most action has completed.\n\n```C#\nvar counter = ObservableValue\u003cint\u003e.From(0);\n\nvar increment = Actions.CreateAction\u003cint, int\u003e(\"Increment\", (amount) =\u003e\n{\n    counter.Value += amount * 2;\n\n    counter.Value -= amount; // oops\n\n    return counter.Value;\n});\n\nincrement(2);\n```\n### Reactions\n\nReactions complete the _MobX triad_ of **observables**, **actions** and **reactions**. They are\nthe observers of the reactive-system and get notified whenever an observable they\ntrack is changed. Reactions come in few flavors as listed below. All of them\nreturn a `IReactionDisposable`, a disposable that can be called to dispose the reaction.\n\nOne _striking feature_ of reactions is that they _automatically track_ all the observables without any explicit wiring. The act of _reading an observable_ within a reaction is enough to track it!\n\n\u003e The code you write with MobX appears to be literally ceremony-free!\n\n**`IReactionDisposable Reactions.Autorun(Action\u003cIReactionPublic\u003e action)`**\n\nRuns the reaction immediately and also on any change in the observables used inside\n`action`.\n\n```C#\nusing Skclusive.Mobx.Observable;\n\nvar greeting = ObservableValue\u003cstring\u003e.From(\"Hello World\");\n\nvar disposable = Reactions.Autorun((_) =\u003e\n{\n    System.Console.WriteLine(greeting.Value);\n});\n\ngreeting.Value = \"Hello Mobx\";\n\n// done with Autorun\ndisposable.Dispose();\n\n// Prints:\n// Hello World\n// Hello MobX\n```\n\n**`IReactionDisposable Reactions.Reaction\u003cT\u003e(Func\u003cIReactionPublic, T\u003e expression, Action\u003cT, IReactionPublic\u003e effect)`**\n\nMonitors the observables used inside the `predicate()` function and runs the `effect()` when\nthe predicate returns a different value. Only the observables inside `predicate()` are tracked.\n\n```C#\nusing Skclusive.Mobx.Observable;\n\nvar greeting = ObservableValue\u003cstring\u003e.From(\"Hello World\");\n\nvar disposable = Reactions.Reaction\u003cstring\u003e((reaction) =\u003e greeting.Value, (value, reaction) =\u003e\n{\n    System.Console.WriteLine(greeting.Value);\n});\n\ngreeting.Value = \"Hello Mobx\";  // Cause a change\n\n// done with reaction()\ndisposable.Dispose();\n\n// Prints:\n// Hello MobX\n```\n\n### Installation\n\nAdd a reference to the library from [![NuGet](https://img.shields.io/nuget/v/Skclusive.Mobx.Observable.svg)](https://www.nuget.org/packages/Skclusive.Mobx.Observable/)\n\n## Credits\n\nThis is an attempt to port [mobx](https://github.com/mobxjs/mobx) to dotnet-standard C# libaray.\n\n## License\n\nSkclusive.Mobx.Observable is licensed under [MIT license](http://www.opensource.org/licenses/mit-license.php)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskclusive%2Fskclusive.mobx.observable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskclusive%2Fskclusive.mobx.observable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskclusive%2Fskclusive.mobx.observable/lists"}