If you want to learn more about the history of Flutter, you could watch the meetup we did at Flock. about Flutter. In this video, I also explain why at Flock. we are excited about using Flutter for mobile development.
In this blog, we will mainly get our hands dirty. We will look at code examples of Flutter, and see how Flutter development can be very similar to that of React.
No JSX, just code
There is no HTML, no CSS, there is not even JSX — in Flutter, there is only code.
Flutter has the same concept as a React “Component”, but here it is a called a “Widget” instead. JSX is not used, as the Flutter team believes that everything can be expressed in code, and that we shouldn’t need a different language for “markup”. The focus is on making Dart as expressive as needed to write markup directly in the language. If you have ever written React without JSX, you may think JSX is a necessary evil, but writing markup directly in code in Flutter feels much more natural than that.
Context instead of CSS
You might wonder: But what about CSS? How can I write a cascading style sheet rule that will display all the text in the app in a specific colour? Flutter abandoned CSS, and its model for applying styles is quite similar to how CSS-in-JS libraries such as emotion (used by Material UI) deal with styles.
Let’s look at a very simple example. What if we would write the most naive version of a Hello World app in Flutter.
We get the following error.
The reason is because Flutter uses context, and this is the exact same idea as React context. When a context widget is provided somewhere in the widget tree, all children of that context widget can read the value of the context. The Text widget needs a Directionality widget as parent to know if the text needs to be placed left-to-right, or right-to-left. We can fix this, by providing the Directionality context in the widget tree.
We can continue like this and provide all kinds of context, such as a DefaultTextStyle, MediaQuery, Localizations, Theme, etc. However, Flutter recommends using a one of their base context providers, such as MaterialApp, CupertinoApp or WidgetsApp, which will take care of setting sensible defaults for all those contexts.
Let’s start with a little scaffold for the material app we are going to build. First, we provide the MaterialApp that instantiate the necessary Flutter context’s. In the home parameter, we provide a Scaffold, which allows us to make a basic material app, with an appBar, a floating action button, a drawer etc.
One of the strong points of Flutter is its editor support. If we want to center the text, we just press our Quick Fix… shortcut, and it will help us refactor our code:
Using the Wrap with Center refactor and the Extract Widget refactor 2 times, we end up with the following code:
As there are no functional widgets in Flutter, you can make functions that return Widgets, but you need to use a class to get the full power of the framework. For example, with classes you get granular rebuilds, you can access context, use hot reload, etc. There is less boilerplate in React if you use functional components, however the Extract Widget Refactor will write this boilerplate for you.
In the above example, we used a StatelessWidget. This hints at the existence of a StatefulWidget, and that is right. However, managing local state with a StatefulWidget requires a lot of boilerplate. We can also use a hooks library, which allows us to manage local state similarly as with React hooks.
Instead of extending a StatefulWidget, we extend HooksWidget. Then we call the useState function with a default value in the build method. The useState hook returns a ValueNotifier object, which has a getter/setter field “value”. We get the “value” in the body of the Scaffold, and we set the value in the onPressed callback of the floating action button. And that’s it! Local state is working.
Reading global state
Now it’s time to make our app a bit more interesting. We’ll add a drawer that uses some global state. The MaterialApp widget in the root of our application inserts a Theme context into the widget tree. This is some “global” state that is available to all child widgets. We can use the BuildContext to access this state in a child of the MaterialApp. It is a convention to use the “of” factory that accepts the BuildContext.
We can now add a Drawer in MyScaffold, that respects the injected Theme:
You can also consider making own custom hook to access the Theme, as useContext will obtain the BuildContext of the building Widget.
Providing global state
But how would we provide our own state into the BuildContext? Say we want to add 3 different pages into our drawer widget, how can we track the currently selected page into some custom global state?
We have the provider package for this. We provide the page state in the Widget tree using Provider.value:
We pass the ValueNotifier<Page> type to the provider, so that we can both get and set the current page. We can access this ValueNotifier using the custom hook usePage:
Both the provider and flutter_hooks package are made by Remi Rousselet:
rrousselGit - Overview
You can't perform that action at this time. You signed in with another tab or window. You signed out in another tab or…
If you are coming from React, you’ll probably like a lot of the packages he made. He’s also the author of the freezed package, which I would recommend if you fancy working with immutable data structures and/or Typescript union types.
I hope this blog post will help React developers get their feet wet with Flutter and, who knows, maybe you get as excited about Flutter as we are in the Flock. community!