Electrode Native Navigation
Today’s mobile-technology climate brings myriad development platforms upon which applications can be built, each with its own advantages and disadvantages. React Native is still a relative newcomer to the field, which brings its own set of challenges. The Electrode Native platform was released in 2017 to assist in overcoming these challenges, allowing a more seamless integration of native and React Native applications.
During development of the Electrode Native platform, a major concern has always been centered around the support of navigation across the entirety of an application; whether the content of any given page was written in a native language, developed using React Native, or a combination of the two.
Given the flexibility and complexity of applications that can be created with React Native, there are many different use-cases for navigation which need to be accounted for, including:
- An integrated React Native application launching a native portion of the application.
- Native code launching an integrated React Native application — at Walmart we have many applications that were initially developed to be fully native, which now wish to incorporate new React Native features.
- One React Native application navigating to a page in another React Native application. Electrode Native was built around the concept of multiple disparate React Native applications inside of a parent native application, so this has always been an integral requirement.
- The ability to perform A/B testing in such a way that features could be compared between their React Native and native versions. Any company like Walmart must ensure that it performs proper A/B testing before releasing any new features, always thinking of the customers’ needs first and foremost.
To address these concerns, we have developed Electrode Native Navigation (ern-navigation), a new navigation framework from the Electrode Native team.
Introduction
Navigation is a core feature of any application; both Google and Apple continue to invest great amounts of effort to streamline their native navigation architecture. The main goal of this project was to empower React Native application developers with the ability to navigate using native components and principles. By doing so, we are able to create reusable, native-friendly pages and applications.
During the development of Electrode Native Navigation, we focused on these core principles:
- We must eliminate the need for a React Native application to maintain its back-stack, and leverage all of the features which are offered by the native framework in managing the navigation queue.
- We must ensure that all transitions between pages and applications use the same animations, whether those pages are built using the native or React Native architecture.
- We must allow for custom layouts — this includes layouts with mixed native and React Native content.
- We must use the native navigation bar managed entirely on the React Native side (this is helpful for existing applications looking to include React Native components inside of their native application).
- We must have the same navigation implementation whether running inside of a standalone React Native application or as part of an integrated native application.
What is Electrode Native?
Before we jump into Electrode Native Navigation, it’s essential to understand what Electrode Native is, and why we have created this framework. Electrode Native allows for the combination of multiple MiniApps (React Native applications) into a single container. The container is generated entirely by the Electrode Native platform and is packaged as an AAR library for Android and as a Framework for iOS (these libraries are similar to standard third-party libraries that Android and iOS developers are familiar with).
Why did we not use one of the existing React Native navigation frameworks?
There are many React Native navigation frameworks to choose from that provide excellent navigation support inside of a single React Native application which requires minimal native integration. Electrode Native Navigation was developed mainly to support:
- A hybrid approach to application development, where multiple MiniApps are built into a library and are integrated with a larger, native application.
- A single React Native application with multiple pages — without an existing native application — which needs a navigation framework.
- An application architecture which allows native and React Native pages to coexist, enabling both native and React Native developers to contribute during an application’s development lifecycle.
Electrode Native Navigation
Electrode Native Navigation (ern-navigation) follows the core principles of mobile navigation. Any flow always has a starting page (its root) and an ending page where a user completes the flow, moving back to that flow’s root. Consider the following example of our MovieApp
developed in React Native using Electrode Native Navigation
Here, the user starts with the Movie List
page (its root). Clicking on the details
button for any movie takes the user to a Movie Details
page, with more detail about the movie. From there, the user can then navigate to the Cast List
page for a more extensive list of the cast who took part in the selected movie.
In a typical React Native application, we register the root component; this allows a native Activity (Android) / ViewController (iOS) to load this component when it is launched. From there, the responsibility for navigation is handed over to the React Native application. Doing so separates the native application from the user flow.
Let’s take the simple example of our MovieApp
above and dive into how Electrode Native Navigation works behind the scenes.
React Native
With Electrode Native Navigation, we register each page inside the app registry to allow a native app to load any React Native page inside an Activity
or ViewController
as needed. Here’s how the components are registered for the MovieApp
using our AppNavigator
.
index.js
The AppNavigator
registers all of the React Native page components, allowing the native applications to load them in any order, on an as-needed basis. If you run the MiniApp standalone, then it starts the initial screen (in this case, MovieList
).
Now, let’s take a look at the MovieList
component and see how it navigates to MovieDetails
page
The MovieList
component extends Electrode Native Navigation’s Component
class which in turn extends React.Component
. The navigationOptions
allows any React Native component to take control of the native navigation bar if they choose to do so, which is beneficial when using a MiniApp from inside a larger native application.
The onNavButtonPress(buttonId)
override allows the MovieList
component to listen and respond to navigation bar button clicks.
Finally, let’s look at how the page navigation works. When a user clicks the View Details button, the component makes a call to navigateInternal(…)
with the name of the next page and the required props. This call will be sent to the native handler via the Electrode Native bridge for processing.
onDetailPress={() => this.navigateInternal('MovieDetails', { movie: movies[activeMovieIndex], configuration, genres })}
Now, let’s take a look at how the native implementation handles these navigate calls.
Android
The native app starts a FragmentActivity
and loads the first Fragment
with the MovieList
component. The View Details button click initiates a navigation call to the MovieDetails
page. The native implementation handles this request by starting a new Fragment
instance with the MovieDetails
view inside it and so on, as demonstrated here:
MovieListActivity (FragmentActivity)
R.layout.activity_main
When the MovieListActivity
is launched, the onCreate()
method of the ElectrodeBaseActivity
will create an instance of the ElectrodeReactFragmentDelegate
and load the Fragment
instance inside of the fragment_container
defined in your activity_main.xml
resource file.
MiniAppNavFragment
can also overridenavigate(Route route)
in case you need to handle a navigation request initiated by React Native.
If navigate(Route route)
is not overridden by either the Activity
or the Fragment
, it falls back to the default behavior wherein a new instance of MiniAppNavFragment
is created and loaded with the specified React Native component.
This design makes the React Native component easily consumable by an Android developer into a preexisting native app.
Electrode Native autogenerates this code whenever a MiniApp is created. This eliminates the need for a React Native developer to learn to write any integration code to run the MiniApp standalone.
iOS
Similarly for iOS, a UINavigationController
would first host the root component inside a MiniAppViewController
; each subsequent navigate()
call from React Native would create a new MiniAppViewController
and load the requested React Native view component inside it.
MovieListViewController (UINavigationController)
When the MovieListViewController
is launched, the viewDidLoad()
will delegate the control to the ENNavigationDelegate
to start a new MiniAppViewController
with the rootComponent
as the view.
MiniAppViewController
You can always extend the MiniAppViewController
to create a custom ViewController
and to override any method based on your requirements. For example, to customize a navigate()
call, you may override the handleNavigateRequestWithPath
function inside your CustomViewController
.
You also have the option to handle this override on the MovieListViewController
level by overriding its navigateWithRoute
method.
Without any overrides in place, the default implementation will be executed, starting a new instance of the MiniAppViewController
with the given React Native component view inside it.
Who is using ern-navigation?
Walmart’s Online Grocery application is the biggest consumer of the Electrode Native Navigation framework, with more than 90% of the application currently using React Native. Additionally, this framework is in use by many applications across Walmart.com, Walmart Canada, and Walmart Grocery as well as other internal Walmart associate-facing applications.
Credits
This article, as well as the Electrode Native Navigation framework, was designed and written by engineers on the WalmartLabs Electrode Native team — Adam Sharp, Deepu Eswarath Ganapathiyadan, and Lianci Liu — under the soft, supple hand of Richard Mercille (you’re welcome, Richard).
Special thanks for the support of the entire Electrode Native team and all of the different Walmart application teams who have helped us along the way — giving us some really long nights and awesome migraines — and we mean that in the best of ways.
Further Reference: