Is Flutter similar to React?

In the weeks of research leading up to my detailed evaluation of Flutter vs React Native, one of the most surprising findings for me was not where the frameworks differ, but how they are similar.

Since I had been working with React as a web developer for many years, my initial expectation was that Flutter, primarily known for developing native applications, would be riddled with foreign concepts for me to learn.

This was not the case.

But how are they similar and does it matter if they are similar? If you have experience with React in either a web or a native environment, it probably does matter to you.

Both Flutter and React use declarative UI#

In the declarative UI paradigm, developers describe (or declare) the current state of the UI and leave the transitioning of UI elements to the framework.

With imperative UI, developers manipulate UI elements directly. I often think of jQuery when I think of imperative UI programming but it is common with pure JavaScript and also in native Android and iOS development as well.

Imperative update with JavaScript#

In this JavaScript example, we are finding a reference to a DOM element and assigning a new value to its style.backgroundColor property.

Declarative update with React#

Similar to the Flutter example, we are binding the backgroundColor style value for the div to the color state variable. When the color variable is updated via setColor, React detects the change and updates the style.backgroundColor property behind the scenes for us.

Again, in this React example, we declare that the backgroundColor is controlled with the color state variable and we update that variable in the call to setColor.

// Declare
return <div style={{ backgroundColor: color }}>/* ... */</div>;

// Update
setColor('green');

Declarative update with Flutter#

In this Flutter example, we are binding the Container widget's color property to the _color variable. When we change the value of the _color variable within the setState function, Flutter detects the change and repaints the widget with the updated color.

In other words, we declare that the backgroundColor is controlled with the _color_ variable and we update that variable in the call to setState.

// Declare
return Container(
  color: _color,
  child: ...
);

// Update
setState(() {
  _color = Colors.green;
});

This declare/update pairing is what makes declarative UI work.

Flutter widgets are React components#

Flutter widgets and React components go by different names but they are built and behave the same. They define the UI elements rendered to the screen and developers can define how these UI elements respond to user interactions.

This is a functional React component that renders a button.

const MyButton = (props) => {
  const { text, onClick } = props;

  return <button onClick={onClick}>{text}</button>;
};

This is a stateless Flutter widget that also renders a button.

class MyButton extends StatelessWidget {
  final Function onPressed;
  final String text;

  MyButton({this.onPressed, this.text});

  
  Widget build(BuildContext context) {
    return RaisedButton(onPressed: onPressed, child: Text(text));
  }
}

Depending on which you are familiar with, one syntax might feel more intuitive than the other, but they are both accomplishing the same goal. Both frameworks also distinguish between stateless and stateful components/widgets. The above examples are both stateless. In React, you can implement a stateful component by incorporating the useState or useReducer (or equivalent) hook. In Flutter, your widget class extends the StatefulWidget class.

Row/Column layout inspired by Flexbox#

Flutter's own Basic widgets documentation says this about Flutter's Row and Column widgets:

These flex widgets let you create flexible layouts in both the horizontal (Row) and vertical (Column) directions. The design of these objects is based on the web’s flexbox layout model.

While flexbox is found in other non-React web applications, you will find many React applications are using flexbox in one way or another.

As with the previous concepts, the syntax is different but the layout principles are the same and also use the same terminology like "space around" and "space between." If you know how to work with one, it shouldn't take you long to learn how to work with the other.

React with flexbox#

In the example below, note how the CSS needs to be explicitly define. You'll see the flexbox definition in the CSS tab:

.box {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

Flutter with Row#

Flutter is similar to React#

After spending many years with React and just a fraction of that time with Flutter, I concluded quickly that these two frameworks are very similar. It even took me some time to realize how much of my React experience is carrying over into Flutter.

New React developers sometimes struggle to figure out how to structure their React components. Questions like "When does it make sense to break one component down into multiple smaller components?" takes some time to learn through experience. That same decision comes into play with Flutter widgets, but if you built that muscle in React, it translates well to Flutter widgets. The same conceptual learning applies to working with declarative UI, managing state, and implementing clean and flexible layouts.

Does it matter?#

Working with similar patterns matters for many developers because sometimes you need to be able to work effectively in any environment and not feel like you need to pick just one and leave the other (and all the knowledge you've built around it) behind. It's okay and encouraged to love both. You can use Flutter for native apps and React for web UI and build great things wherever you are.