OfferUp Adopts React Native in a Move to Build and Launch New Features Faster

At OfferUp we believe in creating simple and intuitive experiences for our community. OfferUp’s mobile apps have been built on native platforms for years. As we started building the next set of capabilities for customers, it was clear that we were going to have to overhaul our apps with a lot of new features and experiences to delight our buyers and sellers, which gave us an opportunity to rethink our technology choices. We wanted to invest in technologies that could help us move faster by focusing on a smaller number of new industry-standard technologies.

OfferUp’s existing offerings have always been more focused on our mobile apps and our web experience has always lagged behind. We knew we wanted to change this to make the web app come to parity with mobile. As we started exploring our choices for the new tech stack, we agreed on some tenets.

  • Consistency: We should build uniform experiences across mobile and web.

  • Reusability: We will encourage and increase code reuse across all platforms.

  • Speed of development: The team should be able to ship quality mobile products on multiple platforms as fast as possible.

  • Future-proof: Our solution would work for not only our initial scope, but one we could use as we added complexity to our apps over the next few years.

  • Team compatible: All of our team members will be able to contribute uniformly to all platforms rather than just iOS, Android or Web.

  • Excellence of User Experience: The app should deliver a user experience as superior as the best native apps in terms of performance (60fps animations and transitions) and system integration (access to camera, push notifications and other device capabilities).

  • Well-supported: Our choice of technology should be well-adopted in the developer community.

We felt that maintaining separate codebases for iOS, Android and web would not be ideal and would not let us build at the pace we wanted, so we started looking at cross-platform options. As our apps added more features, we started realizing that our codebases started diverging and it became increasingly complex to keep them in sync.

We began by evaluating web views or Progressive Web Applications, frameworks like Cordova and Ionic, Flutter and the Dart programming language, and React JS and React Native. As we played with some prototypes, it became clear that React JS and React Native were the most mature and performant solutions out there. React is a well-adopted technology set that will not only help us build beautiful app experiences, but also excite our engineers to learn a cool new technology that could define the future of mobile development. It would also help us attract new, high-quality talent.

There are situations where React Native might not be the right solution. For example, if the app has a lot of complex UI interactions or custom animations suited for games. It might also not lend itself well to apps that use advanced device capabilities and media applications. We discussed the reasons behind one of the earliest adopters Airbnb’s decision to drop React Native. After multiple discussions and diving deeply into an analysis of all of the above, we concluded that for our needs the advantages far outweigh the drawbacks of using React Native. It has been almost 6 months since our decision and so far we feel pretty great about it. We were pleasantly surprised to see significant code reuse between iOS and Android and reasonable re-use between mobile and web. We invested in getting our native engineers trained in React/React Native and Javascript/Typescript technologies and were happy to see everyone enjoying learning new technologies. We feared some attrition, but were in fact thrilled that the entire team quickly adapted to the new technology stack and are now excited to work with React/React Native.

What is React Native and how does it work?

React is a Javascript library for building user interfaces and is currently maintained by Facebook. At the heart of all React applications are components — self-contained modules that render some output. Components are composable — i.e. they might include one or more other nested components in their output. The biggest advantage React provided over traditional UI frameworks was the introduction of the Virtual DOM (Document Object Model), which meant that when data associated with a component in the visual hierarchy changed, only it and its dependant components will be rerendered, thereby eliminating the need for reloading the entire page resulting in highly efficient and fast websites. React Native is a framework that brings React’s revolutionary Virtual DOM over to the native world. This means you can use a best-in-class JavaScript library (React) to build your native mobile user interfaces.

There are two important pieces to each React Native application:

  1. There is a native engine, which runs in each standard native app and handles displaying the elements of the user interface and processes user gestures.

  2. The other one is specific to React Native and executes the JavaScript code in a separate JavaScript engine. JavaScript deals with the business logic of the application. It also defines the structure and the functionalities of the user interface.

These two elements exist on separate threads and never communicate directly or block each other. Between these two threads lies a bridge which is the core that allows React Native to function.

The bridge has three important characteristics:

  1. Asynchronous. It enables asynchronous communication between the threads. This ensures that they never block each other.

  2. Batched. It transfers messages from one thread to the other in an optimized way.

  3. Serializable. The two threads never share or operate with the same data. Instead, they exchange serialized messages.

As we started looking into React technologies, we found that all the capabilities we have and want to offer in the OfferUp product line are available in React JS and React Native. Common features like List, Sign in, Social Logins, Video player, Audio player, Image render, Forms, Tabs, Details views, Navigation and Animations are almost all available out of the box. Additionally we can increase code reuse by writing once and running everywhere. If there are scenarios that do not directly lend themselves to be written directly in ReactNative we can easily switch back into native code and expose it to the javascript layer via the bridge.

Our path to the new OfferUp apps

After we made the decision to move to React technologies, we decided to build a new team with our best mobile and web engineers. The team started creating a plan to ramp up on Javascript, React, and React Native. We provided our engineers access to the best Udemy courses. After a couple weeks of learning, the team divided into smaller sub-teams each focusing on a different basic React concept. We did regular sharing sessions where one of the team members would present their learnings to the rest of the team. Soon the team was building a well-rounded knowledge base and started building our first React Native prototype. We realized that having members' expertise in different areas helps the team build morale and an effective learning environment.

While there are plenty of third-party npm packages available for almost any feature/functionality we realized that the team was interested in building our own packages and we encouraged their enthusiasm. This ensured that we could build our own custom experiences as well as provide engineers the gratification of building uniqueness to the platform.

We found out early enough that the team was interested in picking a unique challenge instead of using vanilla React Native to build the apps. We created a plan to create a React + React Native powered internal framework by building the right set of components, tools and infrastructure to make our development effective, efficient, and productive. We made some early decisions that have helped us:

  1. Create a Design Language System. We created a standard set of interfaces, themes, styles and components that will be used across the entire app to ensure a consistent development pattern. Examples of this are our predefined color palettes, layout definitions, style guides and theming library.

  2. Build a Universal Component Library. We built a set of primitive UI controls and widgets that are reused as building blocks across OfferUp screens. Even though the underlying rendering implementations differ between React and ReactNative, we make sure that we have a common interface for the client screens so that we can use a modular approach for defining our layouts.

  3. Closely partner with design. The decisions to use a design language and Universal Component Library help us closely work with the design team. We use a tool called Storybook to share our components and definitions with the design organization. Design then uses these components to create the screen layouts thereby eliminating the possibility of a mismatch between design and implementation.

  4. Expose backend via a GraphQL service. We decided to set up an Apollo GraphQL service which the client uses to connect with the backend APIs. Using GraphQL helps us consolidate multiple backend queries used for a single operation into 1 query from the client. The GraphQL layer then makes these queries, collects, filters, and collates the data into a single lightweight response payload that it can then send back to the client.

  5. Invest in tooling and testing. We use tools like Jest, Detox, Appium, and Cucumber for our unit test and UI automation test frameworks. Cucumber lets us write automated tests in plain, easy to understand phrases allowing even non-technical people in the organization to write tests for common flows within the app.

Looking forward to our new experiences launching in the summer of 2020

Reducing the number of technologies has helped our team at OfferUp build a deeper expertise around a smaller set of core technologies. It has also helped us make sure we can focus on delivering a uniform experience using a single codebase for both mobile and web. Over the last few months our client engineering team has been building expertise in React technologies and overall we are excited that we made the right decision by switching to React/React Native. We are also planning to share our components and packages back to the React community so other developers can consume and contribute back to our efforts. We look forward to releasing the new OfferUp experience soon.

Sound fun? Come join us!

OfferUp is always hiring and we have a number of roles open across the organization in engineering, product and design. Check them out at https://about.offerup.com/careers/

Authored by Manuj Bahl