{"id":13549993,"url":"https://github.com/chimon2000/remote_state","last_synced_at":"2026-03-06T20:03:24.469Z","repository":{"id":54191830,"uuid":"256542857","full_name":"chimon2000/remote_state","owner":"chimon2000","description":"Tools for mapping data from remote sources in Dart, similar to Elm's RemoteData: https://elmprogramming.com/remote-data.html","archived":false,"fork":false,"pushed_at":"2023-01-22T02:26:56.000Z","size":178,"stargazers_count":14,"open_issues_count":7,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-28T18:05:40.965Z","etag":null,"topics":["remote-data","remotedata"],"latest_commit_sha":null,"homepage":"","language":"Dart","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/chimon2000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-17T15:37:21.000Z","updated_at":"2023-09-23T18:04:43.000Z","dependencies_parsed_at":"2023-02-12T14:03:20.461Z","dependency_job_id":null,"html_url":"https://github.com/chimon2000/remote_state","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/chimon2000/remote_state","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimon2000%2Fremote_state","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimon2000%2Fremote_state/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimon2000%2Fremote_state/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimon2000%2Fremote_state/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chimon2000","download_url":"https://codeload.github.com/chimon2000/remote_state/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chimon2000%2Fremote_state/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30195570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["remote-data","remotedata"],"created_at":"2024-08-01T12:01:27.848Z","updated_at":"2026-03-06T20:03:24.437Z","avatar_url":"https://github.com/chimon2000.png","language":"Dart","readme":"# RemoteState\n\n![Build \u0026 test](https://github.com/chimon2000/remote_state/workflows/Build%20\u0026%20test/badge.svg)\n[![codecov](https://codecov.io/gh/chimon2000/remote_state/branch/master/graph/badge.svg)](https://codecov.io/gh/chimon2000/remote_state)\n[![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](https://opensource.org/licenses/MIT)\n\nTools for mapping data from remote sources in Dart, similar to Elm's RemoteData: https://elmprogramming.com/remote-data.html\n\n| Package                                                                            | Pub                                                                                                    |\n|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|\n| [remote_state](https://github.com/felangel/bloc/tree/master/packages/remote_state) | [![pub package](https://img.shields.io/pub/v/remote_state.svg)](https://pub.dev/packages/remote_state) |\n\n## Slaying a UI Antipattern with Flutter.\n\nLibrary inspired by a blog post by [Kris Jenkins](https://twitter.com/krisajenkins) about [How Elm slays a UI antipattern](https://bit.ly/3j4HFzy).\n\n## What problem does this package solve?\n\nYou are making an API request, and you want to display or do different things based on the status of the request.\n\n## Why RemoteState, not RemoteData?\n\nI gained secondary inspiration from a talk by [Jed Watson](https://twitter.com/jedwatson), [A Treatise on State](https://www.youtube.com/watch?v=tBz3UmZG_bk).  As much as possible, I try to categorize state correctly in my applications.\n\n## The RemoteState approach\n\nInstead of using a complex object we use a single data type to express all possible request states. This approach makes it impossible to create invalid states.\n\n## Usage\n\nA common use case for RemoteState would be mapping it into a UI transition or component state.  Here is an example that uses [StateNotifier](https://pub.dev/documentation/state_notifier/latest/state_notifier/StateNotifier-class.html), found in [examples/counter_state_notifier](https://github.com/chimon2000/remote_state/blob/master/examples/counter_state_notifier)\n\n### [counter/notifier/counter.dart](https://github.com/chimon2000/remote_state/blob/master/examples/counter_state_notifier/lib/counter/notifier/counter.dart)\n\n```dart\n\nclass CounterNotifier extends StateNotifier\u003cRemoteState\u003cint\u003e\u003e {\n  var _counterClient = CounterClient();\n\n  CounterNotifier() : super(RemoteState.initial()) {\n    getCount();\n  }\n\n  getCount() async {\n    state = RemoteState.loading();\n\n    state = await RemoteState.guard(() =\u003e _counterClient.getCount());\n  }\n\n  increment() async {\n    state = await RemoteState.guard(() =\u003e _counterClient.increment());\n  }\n\n  decrement() async {\n    state = await RemoteState.guard(() =\u003e _counterClient.decrement());\n  }\n}\n\n```\n\n### [main.dart](https://github.com/chimon2000/remote_state/blob/master/examples/counter_state_notifier/lib/main.dart)\n\n```dart\nclass ExampleApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      home: StateNotifierProvider\u003cCounterNotifier, RemoteState\u003cint\u003e\u003e.value(\n        value: CounterNotifier(),\n        child: HomePage(),\n      ),\n    );\n  }\n}\n```\n\n### [home.dart](https://github.com/chimon2000/remote_state/blob/master/examples/counter_state_notifier/lib/home.dart)\n\n```dart\nclass HomePage extends StatelessWidget {\n  const HomePage({Key key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    //2. Resolve counter notifier to update state\n    var counterNotifier = Provider.of\u003cCounterNotifier\u003e(context);\n    var counterState = Provider.of\u003cRemoteState\u003cint\u003e\u003e(context);\n\n    var textStyle = Theme.of(context).textTheme.headline4;\n    final fabPadding = EdgeInsets.symmetric(vertical: 5.0);\n\n    return Scaffold(\n      appBar: AppBar(\n        title: Text('RemoteState with StateNotifier'),\n      ),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: \u003cWidget\u003e[\n            Text('You have pushed the button this many times:'),\n            //3. Render state changes\n            counterState.when(\n              initial: () =\u003e Text('Not loaded', style: textStyle),\n              success: (value) =\u003e Text('$value', style: textStyle),\n              loading: () =\u003e Text('Loading...', style: textStyle),\n              error: (_) =\u003e Text('Error', style: textStyle),\n            ),\n          ],\n        ),\n      ),\n      floatingActionButton: Column(\n        crossAxisAlignment: CrossAxisAlignment.end,\n        mainAxisAlignment: MainAxisAlignment.end,\n        children: \u003cWidget\u003e[\n          Padding(\n            padding: fabPadding,\n            child: FloatingActionButton(\n              heroTag: 'inc',\n              child: Icon(Icons.add),\n              //4. Perform increment action\n              onPressed: () =\u003e counterNotifier.increment(),\n            ),\n          ),\n          Padding(\n            padding: fabPadding,\n            child: FloatingActionButton(\n              heroTag: 'dec',\n              child: Icon(Icons.remove),\n              //5. Perform decrement action\n              onPressed: () =\u003e counterNotifier.decrement(),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n```\n\n## API\n\n### RemoteState\n\n`RemoteState\u003cT\u003e` is usedto annotate your request variables. It wraps all possible request states into one single union type. Use the parameters to specify.\n\n- T: The success value type.\n\n### RemoteState.initial\n\n`RemoteState.initial` is an instance of RemoteState that signifies the request hasn't been made yet.\n\n### RemoteState.loading\n\n`RemoteState.loading` is an instance of RemoteState that signifies the request has been made, but it hasn't returned any data yet.\n\n### RemoteState.success\n\n`RemoteState.success` is an instance of RemoteState that signifies the request has completed successfully and the new data (of type T) is available.\n\n### RemoteState.error\n\n`RemoteState.error` is an instance of RemoteState that signifies the request has failed.\n\n### RemoteState.guard\n\n`RemoteState.guard` is a static function that converts a Future to RemoteState.  It will emit RemoteState.error if the future fails or RemoteState.success if the future completes.\n\n## Pattern matching high order functions\n\n### When\n\nThe `when` method is a high order function that accepts a method for each state and matches the request state with the appropriate callback function. All callbacks are **required** and must not be null.\n\n### MaybeWhen\n\nThe `maybeWhen` method is a high order function that accepts a method for each state and matches the request state with the appropriate callback function or a fallback callback for missing methods.  Only `orElse` is required.\n\n### Map\n\nThe `map` method is the equivalent of `when` without the destructuring.\n\n### MaybeMap\n\nThe `maybeWhen` method is the equivalent of `when` without the destructuring.\n\n## State Predicates\n\n### isInitial\n\n The `isInitial` predicate returns true if we haven't asked for data yet.\n\n### isLoading\n\n The `isLoading` predicate returns true if we're loading.\n\n### isSuccess\n\n The `isSuccess` predicate returns true if we've successfully loaded some data.\n\n### isError\n\n The `isError` predicate returns true if we've failed to load some data.\n\n## Maintainers\n\n- [Ryan Edge](https://github.com/chimon2000)\n\n## References\n\n- [How to fix a bad user interface](https://www.scotthurff.com/posts/why-your-user-interface-is-awkward-youre-ignoring-the-ui-stack/)\n\n- [Slaying a UI Antipattern with Web Components (and TypeScript)](https://bendyworks.com/blog/slaying-a-ui-antipattern-with-web-components-and-typescript)\n\n- [How Elm Slays a UI Antipattern](https://bit.ly/3j4HFzy)\n\n- [Slaying a UI Antipattern with Angular](https://medium.com/@joanllenas/slaying-a-ui-antipattern-with-angular-4c7536fafc54)\n\n- [Slaying a UI Antipattern with Flow](https://medium.com/@gcanti/slaying-a-ui-antipattern-with-flow-5eed0cfb627b)\n\n- [Slaying a UI Antipattern in React](https://medium.com/javascript-inside/slaying-a-ui-antipattern-in-react-64a3b98242c)\n\n- [Slaying a UI Antipattern in Fantasyland](https://medium.com/javascript-inside/slaying-a-ui-antipattern-in-fantasyland-907cbc322d2a)\n","funding_links":[],"categories":["Dart"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchimon2000%2Fremote_state","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchimon2000%2Fremote_state","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchimon2000%2Fremote_state/lists"}