Flutter vs React Native
GoogleのDartベースFlutterと、MetaのJavaScript/TypeScriptベースReact Nativeをあらゆる角度から比較します。2025年、どちらのクロスプラットフォームフレームワークが優勢なのか?
少ないコードでコンパイル時の安全性を確保する、急速に進化するproviderアーキテクチャ
event/stateの流れを必須とする、成熟し大規模コミュニティを持つアーキテクチャ規約
「間違った選択」は存在しない――どちらも実績があり、MITライセンスだ。1〜5人の小規模チームで素早く反復開発するならRiverpod:ボイラープレートが少なく、コード生成は任意で、リリースペースも非常に活発(3.4.3、2026-09-03)。複数チームが関わり、監査可能なイベントフローが求められるエンタープライズプロジェクトならBloc:イベント/ステートの分離が必須で、BlocObserverもある。ただしflutter_blocの最新リリースは2025-05-02なので注視が必要だ。問うべきは「どちらが優れているか」ではなく、「規律をどこまで外部から強制すべきか」だ。
| カテゴリー | Riverpod | Bloc |
|---|---|---|
| パフォーマンス | 8/10 | 8/10 |
| 学習のしやすさ | 8/10 | 6/10 |
| エコシステム | 7/10 | 9/10 |
| コミュニティ | 7/10 | 9/10 |
| 求人市場 | 7/10 | 7/10 |
| 将来性 | 8/10 | 7/10 |
// Riverpod - ユーザーリスト(コード生成あり)
// 出典: riverpod.dev 公式ドキュメントのパターン
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'user_list_provider.g.dart';
@riverpod
Future<List<User>> userList(Ref ref, {required int page}) async {
final repository = ref.watch(userRepositoryProvider);
return repository.fetchUsers(page: page);
}
class UserListScreen extends ConsumerWidget {
const UserListScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final usersAsync = ref.watch(userListProvider(page: 1));
return usersAsync.when(
data: (users) => ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) => ListTile(
title: Text(users[index].name),
subtitle: Text(users[index].email),
),
),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(child: Text('Hata: $error')),
);
}
}
// コード生成なしの従来構文による代替案(公式ドキュメント、任意):
final userListClassicProvider =
FutureProvider.autoDispose.family<List<User>, int>((ref, page) async {
final repository = ref.watch(userRepositoryProvider);
return repository.fetchUsers(page: page);
});// Bloc - ユーザーリスト(Event/State + Repository)
// 出典: bloclibrary.dev 公式Core Conceptsのパターン
import 'package:flutter_bloc/flutter_bloc.dart';
sealed class UserListEvent {}
class FetchUsers extends UserListEvent {
FetchUsers({required this.page});
final int page;
}
sealed class UserListState {}
class UserListInitial extends UserListState {}
class UserListLoading extends UserListState {}
class UserListLoaded extends UserListState {
UserListLoaded({required this.users});
final List<User> users;
}
class UserListError extends UserListState {
UserListError({required this.message});
final String message;
}
class UserListBloc extends Bloc<UserListEvent, UserListState> {
UserListBloc({required this.repository}) : super(UserListInitial()) {
on<FetchUsers>(_onFetchUsers);
}
final UserRepository repository;
Future<void> _onFetchUsers(
FetchUsers event,
Emitter<UserListState> emit,
) async {
emit(UserListLoading());
try {
final users = await repository.fetchUsers(page: event.page);
emit(UserListLoaded(users: users));
} catch (error) {
emit(UserListError(message: error.toString()));
}
}
}「間違った選択」は存在しない――どちらも実績があり、MITライセンスだ。1〜5人の小規模チームで素早く反復開発するならRiverpod:ボイラープレートが少なく、コード生成は任意で、リリースペースも非常に活発(3.4.3、2026-09-03)。複数チームが関わり、監査可能なイベントフローが求められるエンタープライズプロジェクトならBloc:イベント/ステートの分離が必須で、BlocObserverもある。ただしflutter_blocの最新リリースは2025-05-02なので注視が必要だ。問うべきは「どちらが優れているか」ではなく、「規律をどこまで外部から強制すべきか」だ。
無料相談を受ける唯一絶対の正解はありません。1〜5人程度の小規模チームで素早く反復開発しており、アーキテクチャの判断をチーム内の会話だけで解決できるなら、Riverpod(ボイラープレートが少なく、コード生成は任意、BuildContextなしでテスト可能)がより適しています。複数チームが関わり、監査可能なイベントフローと厳格な規約が求められるエンタープライズプロジェクト(フィンテックや医療などの規制業界)では、Blocがイベント/ステートの分離とBlocObserverによる一元的なロギングを必須にすることで、より安全な基盤を提供します。