How to utilize the Shoutem platform on top of React Native
Coming from a Cordova/Ionic & AngularJS background, I had the opportunity to act as one of the first developers in the beta phase with the Shoutem platform.
In this post, I am going to recap how I felt building a fully featured application using the Shoutem platform. Here are my biggest challenges , and how I see the Shoutem platform in the app development ecosystem.
On the one hand, I was quite tightly coupled with a few Shoutem internals, but on the other hand, I can also speak from a bird’s eye perspective as a developer using the Shoutem platform as a service. So here we go.
As a developer, you can think of the Shoutem platform as a very flexible layer on top of React Native and Redux. It introduces the new architecture for building React Native apps and comes with a GUI, so non-technical users can build their apps too.
The biggest advantage of the Shoutem platform is that it speeds up the development process of an application. Shoutem encapsulates common app features, called extensions, that can be reused across applications. Shoutem comes with 40+ common app extensions out of the box. Extensions include Login with Facebook, Push Notifications, User Management, etc. You can find a full list of extensions on this github repo.
The important point is the GUI which allows the non-technical users to customize extensions used in the app without even touching any line of code. Furthermore, you can build your extensions from scratch using React Native.
The hardest thing for me was to understand the concept behind extensions and how they interact with one another. Think of an authentication extension that handles Login with Facebook and Login with username/password. Initially, you just develop a standalone authentication extension. But in the context of an application, that extension has to interact quite heavily with other components. For example, an extension where you show some user specific content depending on the logged in user.
Internally, Shoutem uses redux to manage the global state of the application. You can think of the state as a consistent container that is accessible by all extensions. The authentication extension can inject the logged in user into the state, define some internal API for accessing the user from the state and thus any other extension can access the user object in the state.
A good understanding of redux is quite important for writing custom Shoutem extensions.
I was very skeptical of Shoutem at first, because I thought of it as a usual App Builder on the market. And as we know, App Builders are far from being customizable, flexible and open for developers.
I learned quickly that Shoutem is not an app builder — it is the platform for React Native developers which among other parts has a GUI for managing apps. GUI provides an easier connection between developers and their clients. I am going to present a short example that I faced, to illustrate what I mean by saying flexible and open for developers.
While integrating Push Notifications using Firebase Cloud Messaging in my app, I took use of the shoutem-firebase extension that encapsulates all firebase specific components in one extension.
The first thing you do is to go to the app builder and install the shoutem-firebase extension.
Installing the Firebase extension for your app via the App Builder
The next time you run your app locally using the Shoutem CLI
shoutem run-ios <your app id>
you get the shoutem-firebase extension bundled into your React Native app. Just for the record, Shoutem bundles your React Native application to ~/.shoutem/platform/build.
So from this point onwards, the firebase extensions resides inside your app. So far so good, but to take use of Push Notifications I needed the Firebase Cloud Messaging Token to be sent to my own backend and associated with a user. Furthermore, I wanted to trigger the “Ask for push notification permission dialog” at a specific point in the app, and not immediately after the app starts up. So, I had to do some customisation to achieve it, and that’s also where the power of the Shoutem platform comes into play.
The shoutem-firebase extension internally fires a redux action called REQUEST_PUSH_PERMISSION, that when fired is caught by some redux middleware to display the “Ask for push notification permission dialog”. All those fired actions can be seen by any component in the whole application. That’s also the point where I injected my logic. So the first thing I fired was the REQUEST_PUSH_PERMISSION action, when I wanted to display the dialog. So I fired this redux action from my Shoutem extension.
screens/MyOwnScreen.js
componentDidMount() {...this.props.actions.requestPushPermission(access_token);...}
redux.js:
export function requestPushPermission(accessToken) {return { type: REQUEST_PUSH_PERMISSION, accessToken: accessToken};}
So what this snippet does, is that when the MyOwnScreen.js gets mounted a REQUEST_PUSH_PERMISSION action is fired. At this moment, this action gets fired twice, once from the shoutem-firebase extension and the second time from my own extension. To prevent the default action, I installed a custom middleware in my own shoutem extension.
middleware.js
const requestPermissions = store => next => action => {if (action.type === REQUEST_PUSH_PERMISSION) {
if (action.hasOwnProperty(‘accessToken’)) {
FCM.getFCMToken().then(token => {
console.log(‘Firebase device token:’, token);
// TODO: send the token to your backend
// show the request push notification permission dialog
FCM.requestPermissions();
} else {
return next(action);
}
}
};
setPriority(requestPermissions, priorities.FIRST);
This custom middleware listens for the REQUEST_PUSH_PERMISSION action and checks if the received action contains an accessToken (only the custom action has the accessToken in it). If the action contains an accessToken, the middleware recognizes the custom action fired from inside MyOwnScreen.js. When the action is fired, the middleware sends the received token to the server, and the push notification permission dialog is displayed. Otherwise, it dispatches the action to the next middleware. With the last line, we make sure the middleware is the first in line to be called.
This example should give you some insight on how easy it is to extend the functionality of existing extensions without touching the shoutem-firebase extension at all. If you like you can also extend the default shoutem extensions with your own logic, they are all open source, or you can write your own extensions from scratch.
In the end, the app you build with Shoutem boils down to a plain React Native application, and every single aspect is in the palm of your hand as a developer.
Without any React Native / Redux background, before starting with the Shoutem platform it was not easy to get the overall concept right in the beginning. To be honest, Shoutem adds some complexity to the overall stack, especially when you have never used React Native / Redux before. But once you understand the concept, benefits are numerous and it all feels natural and logic to you.
I see great potential in the concept behind the Shoutem platform as more and more developers adapt to it. Shoutem establishes a clean, professional layer on top of React Native that can be used in different ways. The platform provides a simple to use graphical App Builder for building apps without writing a single line of code. More importantly, the platform doesn’t cut any flexibility building apps by introducing the concept of extensions and letting third-party developers the choice to build completely own extensions from scratch.