Top 7 Simple Patterns To Upgrade Your React Native Applications
For any app or product, good performance is crucial. During your work with React Native, you can often face performance problems. This is why you need to focus on best practices and performance improvement for your React Native app in its development, to resolve these problems and to provide end users with a flawless experience.
In this article, we will walk you through 7 useful patterns that may help you when developing your React Native apps.
Top 7 Simple Patterns To Upgrade Your React Native Applications
Keep the majority of your components simple
This applies to any React application. Your views and components should depend on props and callbacks, whereas Container (smart) components should rely on state. I recommend Redux, but in some cases, setState will work nicely. MobX is another excellent option for performance improvement.
Rely on callbacks
You might have been taught to use the delegate pattern to decouple a View from its Behavior when learning how to code iOS apps in Swift. Callbacks can be used to achieve the same effect in React Native. Callbacks are purely Arrow Functions that can be passed to a component. The component is responsible for carrying them out, but it is not required to understand what it is doing.
The majority of components should not have any behavior. Simple callbacks should be exposed; they act as your components' public API. Reading their names should give you an idea of when they'll be executed. If you're creating an e-commerce app, names like onSelectProduct or onProductAddedToShoppingCart are very descriptive.
When deciding whether or not to expose a callback, consider the following:
Is this interaction only important for this component, or can it trigger changes in other parts of the application? If you choose the latter option, you should expose a callback.
Keep your callbacks chained together
A very common pattern is to inject behavior into higher-order components (that's what the mapStateToProps of Redux does), but many overlook that there can be a public callback in another part of the application (an outer component, for example).
Invoke the actual callback passed on to props every time one of your views expose a callback that may be used in another part of your application (such as mapStateToProps). This allows you to navigate to your screen, for example, and also to collect information to feed the next view.
As you can see, each realm has its own set of rules: screens know how to navigate, connected views know how to handle redux actions, and views are dumb, stateless, and reliant on their props.
Keep your reducers simple and declarative
Any developer should be able to understand what your reducer is doing by looking at its code. In most cases, having one function for each type of action can improve readability.
You can gain more flexibility and code reuse by composing your reducer functions with many one-line functions.
We were able to migrate this application from React Native's default Navigator to NavigationExperimental, and then to React Navigation. These modifications required only a few lines of code. The concept is easy:
Screens and Views are not the same thing. Views should not be aware of the Navigation Stack, whereas Screens (or Routes, depending on which name you prefer) must be aware of how to navigate and communicate with the Navigation Bar / TabBar. Your screens will simply wrap the actual Views in navigation-aware things if you take this approach. For example:
FavoritesView, as you can see, simply exposes an ‘onSelectFavorite' callback and is unconcerned about what it actually does. That callback is used by FavoritesScreen to instruct the navigator to move to another screen. As a result, you have the flexibility to replace the way your navigation stack works and excellent separation.
Keep platform-specific components to a minimum
Don't get me wrong: every platform has its own Design/UX language, and in many cases, you must write multiple versions of a component. Remember that the React Native motto is “learn once, write anywhere,” but don't rush into writing platform-specific components first.
Simple Style changes and conditional operators are sufficient in many cases. I wrote a simple helper function called platformSpecific that allows me to set styles based on a platform.
Keep business logic out of your Reducers
Your Redux store is not a part of your business model; it is a View Model. Treat it as such. Changes to your reducer should only have an impact on the store, and you should be very confident in them. The less your Reducers know about your business rules, the simpler they will become.
It's not the best approach, but it's a better one to put your business logic in action creators, especially if you're using a middleware like Thunk. Epics and sagas are also fantastic.
Even if you do not use these patterns, it does not matter. The key point that everyone should know is to keep things simple and separated. Performance improvement and easier testing will be the result. Many of these patterns and practices can help you accomplish this.
If you are looking for a technology partner to help you improve your React Native applications, Groove Technology with experienced developers can take your application to the next level. Do not hesitate to contact us via: contact@groovetechnology.com
References
Santiago Ignacio Poli, (2017), 7 Simple Patterns to improve your React Native Experience.