Migrating from React Native to Flutter
By Ann Tech · 28 April 2026
If you're coming from React Native, Flutter is more familiar than it looks — and more different than it seems. Here is a practical mapping between the two worlds.
Mental model shift
| React Native | Flutter |
|---|---|
| JSX components | Widget classes |
| StyleSheet.create | Theme / TextStyle / BoxDecoration |
| useState / Redux | setState / Riverpod / BLoC |
| React Navigation | go_router / Navigator |
| FlatList | ListView.builder |
| Expo | FlutterFire / pub.dev packages |
| Metro bundler | flutter build |
Layout
React Native uses Flexbox everywhere. Flutter uses a tree of layout widgets:
// React Native
<View style={{ flexDirection: 'row', alignItems: 'center', padding: 16 }}>
<Image source={{ uri: url }} style={{ width: 48, height: 48 }} />
<Text style={{ marginLeft: 8 }}>{name}</Text>
</View>
// Flutter equivalent
Padding(
padding: const EdgeInsets.all(16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.network(url, width: 48, height: 48),
const SizedBox(width: 8),
Text(name),
],
),
)
Flutter's layout widgets (Row, Column, Stack, Padding, Center) feel verbose at first but are predictable once learned.
State management
// React Native: useState hook
const [count, setCount] = useState(0);
<Button onPress={() => setCount(c => c + 1)} title="Add" />
// Flutter equivalent: StatefulWidget
class Counter extends StatefulWidget {
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int count = 0;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('Count: $count'),
);
}
}
For global state, Riverpod is the closest to React's Context + hooks mental model:
// Riverpod feels familiar to React developers
@riverpod
class CartNotifier extends _$CartNotifier {
@override
Cart build() => Cart.empty();
void add(Product p) => state = state.copyWith(items: [...state.items, p]);
}
// In widget (like useSelector):
final cart = ref.watch(cartNotifierProvider);
// To dispatch (like useDispatch):
ref.read(cartNotifierProvider.notifier).add(product);
Navigation
// React Navigation
navigation.navigate('ProductDetail', { productId: '123' });
navigation.goBack();
// go_router
context.push('/products/123');
context.pop();
// Or:
context.go('/products/123'); // Replaces stack entry
Styling
React Native styles are JS objects. Flutter uses widget properties and themes:
// React Native
const styles = StyleSheet.create({
card: {
backgroundColor: '#ffffff',
borderRadius: 12,
padding: 16,
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 4,
},
});
// Flutter
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
padding: const EdgeInsets.all(16),
child: child,
)
What's genuinely better in Flutter
- Hot reload is faster and more reliable
- Consistent rendering — no native component differences between Android and iOS
- Performance — AOT-compiled Dart is faster than JavaScriptCore
- Type safety — Dart's sound null safety catches bugs the JS type system misses
- Testing — widget tests are easier to write and faster than RN equivalents
What takes getting used to
- Verbose widget tree syntax (no JSX)
- No direct DOM/native manipulation
- A new package ecosystem (pub.dev vs npm)
- Dart instead of JavaScript/TypeScript
Common pitfalls
Expecting JSX-like syntax. Dart doesn't have JSX. Widget trees look verbose compared to JSX but are just regular Dart constructors — they're more typesafe and IDE-friendly.
Importing npm packages. React Native uses npm/yarn. Flutter uses pub.dev and pubspec.yaml. The package ecosystems are separate — RN packages don't work in Flutter.
Using StatefulWidget everywhere. In RN, state with useState is natural. In Flutter, reach for Riverpod for anything shared across screens and use StatefulWidget only for local UI state.
Sign in to like, dislike, or report.