{
  "id": 11226935,
  "title": "Riverpod vs Bloc: Fixing the FutureBuilder Anti-Pattern",
  "url": "https://urgent.news/2026/10/01/riverpod-vs-bloc-fixing-the-futurebuilder-anti-pattern",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-01T15:55:35.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/renato_silva_71eef0fc385f/riverpod-vs-bloc-fixing-the-futurebuilder-anti-pattern-30d4"
  },
  "original_language": "en",
  "account": "The article discusses the anti-pattern of placing asynchronous operations, like network requests, within the `build()` method of Flutter widgets. This leads to repeated data fetching on every widget rebuild, which can cause issues like missing cached data, rate limit hits, and stale data. The solution proposed is to move these async operations into an architecture layer that outlives individual widget rebuilds.\n\nTwo approaches are explored: Riverpod and Bloc.\n\nRiverpod introduces the concept of `FutureProvider` or `AsyncNotifier`, which moves the async call outside the widget tree. The provider is keyed by its arguments, cached, and only re-executes when its dependencies actually change. In the example provided, the `UserProfileScreen` widget uses `ConsumerWidget` to watch for changes in the user provider. When the data is available, it displays the `UserCard`; if loading, it shows a circular progress indicator; and if an error occurs, it displays an error message. This approach ensures that the network call is made only when necessary, and results are reused when possible. The trade-off is the need for code generation and understanding of providers as part of a dependency graph.\n\nBloc, on the other hand, models every asynchronous phase as a discrete state using a state machine. It introduces a `UserCubit` that owns the state transitions between loading, loaded, and error states. The `loadUser` method is called once in the `create` method of `BlocProvider`, and the state transitions are managed explicitly. The `UserProfileScreen` widget then listens for state changes using `BlocBuilder`, displaying appropriate UI based on the current state. While this approach can lead to more verbose code with explicit state classes and boilerplate, it offers a clear, testable state machine and a replayable transition log, which can be valuable for debugging and in regulated environments.",
  "summary": "🔧 The Problem If you've worked on a Flutter codebase for more than a few sprints, you've seen this pattern: dart class UserProfileScreen extends StatelessWidget { final String userId; const UserProfileScreen({required this.userId, super.key}); Future _fetchUser() => UserRepository().getUser(userId); @override Widget build(BuildContext context) { return FutureBuilder( future: _fetchUser(),…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}