React Native: Idea to Product in One Week
Over at Adjust Creative, we’ve been interested in the shared code library that React Native offers for a while now and we love pulling up our sleeves and digging into fresh technologies — especially if they can help us and our clients.
We decided to develop an app to understand the workflow of producing a product with the React Native framework.
The outcome of our design & prototype sprint is roughly 35 hours worth of a beautifully designed—single function application that let’s us (and you) browse headlines from our favorite design blogs. We didn’t choose all design blogs because we think good design matters and we’ve curated a couple of our favorites.
We like it and you probably will too.
Let’s talk about what it was like to go through the design sprint.
Decision Making: Keep. It. Simple. Stupid.
We kicked-off with a few different ideas about what we could prototype or build to test our assumptions about the React Native framework. But, we didn’t necessarily want to spend a lot of time testing out complex features or going all-in because we have awesome clients that we spend a lot of time working with.
This had to be executed quickly and with minimal development cost/time.
We started with these rules:
- Don’t make something super experimental or overly animated
- Don’t overthink it.
And these goals:
- Prove our theories and assumptions about React Native
- Provide an app that has at least some value with the experiment (no throw away code)
These goals were definitely accomplished and the rules were mostly followed. Although, there’s a fair amount of pretty animations. :)
Some of the possible ideas we kicked around were: Instagram or Flickr images by location, visual poetry, single function social community, surprise learning, inspiring quotes, an animated story, beer menu’s or a design industry news aggregator.
We liked the design news aggregator most because there’s not a lot on the backend and it is useful to us and our industry friends.
The decision was fast and easy.
Colorful, Animated & Designery
It took us about 8 names shouted out (into Slack) and a bit of thesaurus searching to come up with the name Peruse.
Coming up with the aesthetic wasn’t too bad either, we like the simplicity of Founder Mantras, and we dug up some inspiration via the blog feeds that we decided to put into the app to give us a jumpstart in visual design style.
Then we went to it!
The first thing we did was sketch, concept and mockup the app store icon and a “loading” screen.
We wanted to design a “P” that looked kinda like our Adjust Creative logo (or “shark fin” as it’s sometimes referred internally)—because branding.
Using the research I did about designing for iOS and Android, we decided that this app is simple enough that it could be designed, for the most part, the same on both operating systems.
The design of the app is super simplistic and a great example of modern flat design—but with depth.
Each news item is a page is colored randomly with a solid color chosen from an array of flat colors and the navigation transitions use a 3D effect.
Tools used: Pencil, Paper, Adobe Photoshop, Adobe Illustrator and the awesome UI tool Sketch.
Let’s move on to some programming stuff…
Getting Started with React Native
Josh wrote an article explaining React Native from a non-programmer’s perspective and we’ve programmed a couple of applications for web browsers using React. I’ve developed applications with iOS and helped with some on Android in the past. So, we had a pretty good understanding of the platform and what it brings to the table.
That said, hitting the ground running wasn’t bad for me because I’ve been programming things for 17 years. A lot of the research was done on the fly and I’ll try to outline some of my thoughts below.
Note: If you’re new to programming — this article is not going to get you up to speed as it covers a couple of topics, but there is no finished production code to use in entirety.
Getting setup for iOS was streamlined, a couple of terminal lines to generate a starting boilerplate, set a couple of configuration spots in Xcode and go!
For Android on the other hand, I had quite a few hick-ups because I didn’t have the proper Java SDKs and things like that. The setup for Android environment took me a fair amount of thorough reading and wasn’t as straightforward as I thought it would be. However, I did get past all the environment setup and into my first ReactNative error (backgroundImage fail) in about 2 hours.
Get that data!
First things first, I needed some data to play with. Luckily, Yoni Weisbrod wrote a great article about loading data with React Native.
I wrote a couple of functions to fetch the feeds and run them through the Google Feed API so that they would have a consistent data structure.
Each time a feed loads, it runs through this function that checks to see if all feeds are loaded (or error’d) and parses the data into a stored data object for setting the component state with later.
Once the data is loaded, I fire off the function startSwipeComponent() and we get into the feeds.
Loading, loading, spinny wheels, bla bla…
Did you ever see the website Pretty Loaded? Some friends over at Big Spaceship made it back when I was working at Domani Studios. We made a lot of websites with Adobe Flash and since they were pretty heavy files, most of the time we needed SICK PRE-LOADERS BRO. (look for the one with dripping countdown)
Also, side note: We didn’t make those ugly flash sites that everyone hated. We made truly immersive experiences that were highly interactive, engaging and the User Experience was… ahem… ahead of it’s time. (and still do)
Anyway, the in the loading screen, I’m using React Native’s Animated component to drop in the logo and fade in the shadow. It’s quite easy to implement and reminds me of the patterns used in TweenLite or for the old-school, MCTween.
Custom Swipes and 3D transitions and stuff
This was the only part where I didn’t get to use the simple React Native components. It took the longest because I had to custom program the View controller.
React Native provides you with a couple of out-of-the-box navigation utilities like Navigator & NavigatorIOS. But, after a couple of failed attempts at trying to extend them for my purposes, I decided to just write a swiping page controller myself.
I knew that I wanted it to have a left/right Tinder style swipe to go through each post (minus all the photos of people being super cool in a different country) and that I wanted the transitions from post to post to be elegant and feel very comfortable to use.
So, I went to town programming my own View controller, which may get added to npm because people seem to like it.
I’m not going to go full into the entire component in this article, but I do want to outline a couple parts of core functionality.
There are only 3 Views at any given time.
There’s no reason to create View’s all the time and there’s not enough CPU to generate a new View for each item in the data. So, the three views get updated with the relevant current data and the controller moves them around while you use your finger back or forward.
To be honest, it should probably just be two views and the “next” one is decided by the direction you’re moving, but I like thinking of them on either side for some reason and it’s really not much different in terms of overhead.
PanResponder is nice.
The math to move the Views happens in a couple places and is controlled by PanResponder.
The most important is the “on move” and the “on end” event listeners. With each movement, the positioning gets saved and the most important value for this controller is the horizontal distance variable, “dx”.
Once you lift your finger, it triggers an animation to finish what you started or snap back depending on where you let go. I tried to use the Animated library, but in the end I just had to write it myself using requestAnimationFrame to make it work the way I wanted it to.
This is the “user let go” function:
You can see that there’s a bit of custom math to get the right animation speed and ease, but the function doesn’t do much more than store where the current “dx” is.
The real meat of the controller component is in the render() function of the component where it sets the stylesheet for each of the three views.
With a little trial and error, I found the right calculations that made the Views fade away and rotate on their Y axis to feel like they are sort of “falling” away from the screen.
The component stack is called every frame on Animations…
This way of programming animations in React is a little worrisome because we have to render the entire state and component stack with every frame tick. From experience, I know that this isn’t a good design pattern for performance gains.
But, after reading Facebook’s long article on React Native performance and this article by Tal Kol—I’m convinced that it doesn’t matter either way and we just wait for the React Native framework to get better or develop custom modules with native code.
If you want to squeeze performance out of a device, you have to use the language that is intended by the device makers—no way around it. But, we’re talking about React Native and developing for shared codebase for multiple platforms—not about squeezing every ounce of power from a system for graphics like the DemoScene crazy heads.
So, on with the show.
All devices are not created equal.
The first version was developed for an iPhone 6s with iOS9 and midway through updated to iOS10 beta. Probably not such a good idea to switch to the beta midway through building, but clients have needs. Plus, it only took a few minutes to upgrade to the new Xcode and get it realigned.
I then branched an iOS9 version for an old iPod we have at the office running at the speed of an iPhone 4. On said device, everything works, but the animations are choppy and s l o w. Not much I can (or want to) do about it.
Even still with these minor changes—this is a HUGE leg up from programming in two vastly different languages.
The two biggest noticeable differences in Peruse are:
- the perspective of the 3D flipping function
- SafariView opening an in-app browser view on iOS versus Linking.openURL just opening Android’s default browser.
PanResponder takes over child component interactions.
It was frustrating trying to figure out how to get the one button that views the full article on each slide to work while PanResponder was watching for interaction. I found a couple of ways to get around this and a thread about it on the React Native Github.
Not going to go too far into this, but there were a couple of things that helped get a compiled version of the app on my phones.
For iOS, there are two lines in AppDelegate.m that get reversed depending on if you want to use the emulator or the device. I know there’s a smarter way to do this, but I’ve just been commenting one or the other as needed:
On the Android side of things, I didn’t even really open Android Studio once I got quick with Terminal.
I will say that this article on Facebook (along with some google searching) was extremely important and sometimes you have to stop the Gradle daemon because it holds onto environment variables:
I’m not going to dig into the deploying for public portion as there’s plenty of documentation on that from both Apple and Google.
We’re done here. For now…
I had a great experience developing this simple app, I’m excited to see the React Native community grow and I can’t wait to dig in to something a bit more robust using the framework.
I imagine that if I spend enough time with it, I’ll eventually loath certain things. But, it’s a solid framework that helps cut down development time and cost by allowing front-end web programmers to join the mobile app dev process.
Designers and Developers:
We would love to see this app grow with the help of the design community with new features and control over feeds. If you’re interested in contributing or making it better, please comment below and and maybe we can fork the project, add you as a developer on Github or at least get a feature request roadmap on Trello.
You can find me and Adjust Creative pretty easily to tell us how much you like or dislike the app, if you found this article helpful in any way, if you want to contribute or just say hi.
Here are a couple more links & code chunks that were valuable enough to share but didn’t really fit into the article.
Unused React Native triangle generator code…
I tried to implement some dynamic graphics into the app in the background of the pages, but it renders far too slow for such things. I would have to do this in a lower level programming language and spend more time than necessary for a subtle effect.
If you’re interested in toying with it, you can have it. It uses jpoliachik’s triangle view.
Facebook on building the F8 Conference app with React Native: http://makeitopen.com/tutorials/building-the-f8-app/design/
Excited to try some of these components: https://blog.redradix.com/6-essential-libraries-to-use-on-your-next-react-native-app/
These fonts are awesome: http://www.demilked.com/21-beautiful-free-fonts-every-designer-must-have/
Sketch iOS App Icon template: https://www.dropbox.com/s/ejv2sxmfy8vhqz1/savvy_apps-icon_template-update_04_14.sketch?dl=0
React Components on FB: https://react.parts/native
iOS exporting for remote testing: https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/TestingYouriOSApp/TestingYouriOSApp.html
In case you get the Android Blur issue: https://github.com/500px/500px-android-blur/issues/26
Android Studio Install: https://developer.android.com/studio/install.html
Android app icon locations: http://stackoverflow.com/questions/34329715/how-to-make-react-native-app-icon