Get AI summaries of any video or article — Sign up free
React Native vs Flutter - I built the same chat app with both thumbnail

React Native vs Flutter - I built the same chat app with both

Fireship·
5 min read

Based on Fireship's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Flutter renders UI using its own C++/Skia engine and compiled native code, often reducing bridge overhead compared with React Native.

Briefing

Cross-platform mobile development comes down to a tradeoff between Flutter’s “batteries-included” approach and React Native’s JavaScript-first flexibility—but the biggest practical difference shows up in how each framework renders UI and how much friction developers face while building and iterating.

Flutter, built by Google, uses Dart and its own rendering engine to draw UI directly. Instead of relying on native UI components, Flutter compiles to native code and renders its own pixels (via a C++ engine and Skia). That design reduces reliance on a JavaScript-to-native bridge, which is central to React Native’s architecture. The result is typically smoother performance and more consistent visuals across iOS and Android, with the added ability to paint custom graphics like a game engine. When native features are needed, Flutter uses platform channels to communicate with the device layer.

React Native, from Facebook, is built around JavaScript and React. It runs two JavaScript threads—one for the app’s main work and one for business logic—and uses a bridge to pass serialized messages between JavaScript and native code. UI components ultimately become truly native on each platform, not a “web app in a wrapper,” but the bridge still shapes performance characteristics and can become a bottleneck as apps grow. React Native’s philosophy is minimal: it provides base components and expects developers to assemble the rest from third-party libraries, which can mean more dependency management and more choices.

The developer experience mirrors those philosophies. React Native starts with npx react-native init (or often Expo) and produces a project full of configuration and tooling files—Metro for hot reloading, Watchman for file watching, Babel for transpiling, and build tooling like Buck. Iteration relies on Metro plus hot reload, which preserves app state while reflecting code changes. But the ecosystem is more “choose your own adventure”: teams may add TypeScript, adopt Ignite for boilerplate, or swap in Expo depending on preferences.

Flutter’s setup is typically faster because it doesn’t require pulling in as many packages up front, and the Flutter extension in VS Code can manage dependencies automatically. Code lives in main.dart with configuration in pubspec.yaml. Dart’s type system and null safety provide stronger guardrails during development, catching many issues before runtime—an advantage for mobile apps where app-store reviews make bugs expensive. Flutter also supports hot reload (leveraging just-in-time compilation), and its tooling can surface documentation and type information directly in the editor.

Both frameworks use declarative UI trees inspired by React: React Native uses JSX with components like View, while Flutter uses classes with a build method that returns a widget tree. Flutter’s approach can lead to deeply nested widget structures that are harder to read unless developers extract custom widgets, while React Native can require more work to find or create components that match exactly what the UI needs—especially when desired libraries don’t support React Native.

After building the same chat app with Firebase as the backend, the performance picture leans toward Flutter in benchmarks, often getting closer to native 60fps targets. Still, the transcript cautions that for many real-world apps, performance differences may be indistinguishable to users, making the choice less about raw speed and more about ecosystem fit, developer workflow, and how comfortable teams are with Dart versus JavaScript.

Cornell Notes

Flutter and React Native can build the same cross-platform apps, but they differ sharply in rendering and development workflow. React Native runs JavaScript on two threads and uses a bridge to communicate with native code, relying on third-party libraries for many features. Flutter uses Dart plus its own rendering engine (C++/Skia) to draw UI directly, reducing bridge overhead and often delivering closer-to-native performance. Dart’s type system and null safety improve error detection during development, while React Native’s JavaScript ecosystem offers flexibility but can increase dependency and decision fatigue. The “best” choice depends on whether a team prioritizes Flutter’s consistency and tooling or React Native’s JavaScript familiarity and modular ecosystem.

How do React Native and Flutter differ at the rendering/architecture level, and why does that matter?

React Native runs JavaScript on two threads (main UI work and business logic) and uses a bridge to pass serialized messages between JavaScript and native code. UI ultimately becomes native components, but the bridge can influence performance. Flutter instead uses its own high-performance rendering engine (C++ with Skia) to render custom pixels compiled to native code, aiming for pixel-perfect iOS/Android widgets without needing a bridge for normal rendering. When native integration is required, Flutter uses platform channels.

What does the transcript suggest about developer experience during setup and iteration?

React Native setup often starts with npx react-native init (or Expo), then relies on Metro and Watchman for hot reload and file watching. Iteration uses hot reload that preserves state while reflecting code changes. Flutter setup uses flutter create and the VS Code Flutter extension to manage packages automatically; iteration uses flutter run plus hot reload supported by Dart’s just-in-time compilation. The transcript also notes Flutter’s editor tooling benefits from Dart’s type system and documentation hover.

Why is Dart’s type system portrayed as a practical advantage for mobile apps?

Dart’s sound type system and null safety help prevent runtime errors by flagging wrong argument types during development. The transcript frames this as especially important for mobile apps because app-store reviews make bugs costly after release. React Native can add TypeScript for similar benefits, but Flutter’s built-in guarantees are presented as more direct and reliable.

How do the two frameworks handle UI composition, and what tradeoffs appear when coding by hand?

Both build declarative UI trees. React Native uses JSX with components like View and re-renders when state changes. Flutter uses classes with a build method that returns a widget tree, where widgets are class instances with properties that can include other widgets. The transcript’s tradeoff: Flutter can produce deeply nested widget trees that are hard to follow unless logic is extracted into custom widgets, while React Native can require more searching for components or third-party packages that fit, and some libraries may not be compatible with React Native.

What performance conclusion does the transcript reach, and what caveat tempers it?

Performance benchmarks generally favor Flutter, with the transcript attributing the edge to compiled native code and reduced dependence on a JavaScript bridge. The goal is often 60 frames per second and closer-to-native behavior. The caveat: many apps won’t show meaningful differences to end users, so performance may not be the deciding factor unless an app is particularly performance-sensitive.

Review Questions

  1. Which architectural mechanism in React Native enables JavaScript-to-native communication, and how does Flutter avoid relying on it for normal rendering?
  2. What specific Dart features (as described) reduce runtime errors, and how does that compare to React Native’s optional TypeScript approach?
  3. What UI-structure tradeoff does the transcript highlight for Flutter widget trees versus React Native component composition?

Key Points

  1. 1

    Flutter renders UI using its own C++/Skia engine and compiled native code, often reducing bridge overhead compared with React Native.

  2. 2

    React Native runs JavaScript on two threads and uses a bridge with serialized messages to interact with native code, which can affect performance as complexity grows.

  3. 3

    React Native’s minimal core pushes many features into third-party dependencies, increasing dependency management and decision fatigue.

  4. 4

    Flutter’s default widget library and Dart tooling (including null safety and strong typing) provide earlier feedback and fewer runtime surprises.

  5. 5

    Both frameworks use declarative UI trees, but Flutter’s widget nesting can become difficult to read without extracting custom widgets.

  6. 6

    Hot reload is available in both ecosystems, with React Native relying on Metro/Watchman and Flutter leveraging Dart’s just-in-time compilation.

  7. 7

    Performance benchmarks often favor Flutter, but the transcript cautions that many apps may not show user-visible differences.

Highlights

Flutter’s rendering engine draws its own pixels via C++ and Skia, aiming for pixel-perfect iOS/Android widgets without a rendering bridge.
React Native’s two JavaScript threads communicate with native code through a bridge that passes serialized messages.
Dart’s sound type system and null safety are presented as practical tools for catching errors before runtime—important for mobile app review cycles.
Flutter can lead to deeply nested widget trees, while React Native can require more component/library assembly and may face compatibility gaps.
In benchmarks cited in the transcript, Flutter tends to get closer to native performance, though the end-user impact may be negligible for many apps.

Topics

  • React Native vs Flutter
  • Cross-Platform Rendering
  • Developer Tooling
  • Hot Reload
  • Performance Benchmarks