Cross-posted to Medium by our VP of Engineering, Jani Eväkallio.
This week, we started writing a new React Native app. With every new project, I experience a mix of giddy excitement and intense anxiety: an opportunity to right all past mistakes, and a chance to make a thousand new ones.
Discussing greenfield tech choices inevitably devolves into bikeshedding. “Uhh, so which async redux middleware should we use?” is an incredibly common time-sink, and at the end of the day, probably not the choice that will decide the success or the failure of your software product.
That’s why a year ago I wrote Pepperoni, a React Native boilerplate to end bikeshedding once and for all. Except, of course, it didn’t end. In the year since, everything’s changed!
I still believe that boilerplates are useful to ramp up new projects quickly, but not to enforce library choices. There’s no one-size-fits-all solution.
Instead, I wanted to share our latest choices as a list, and give shout-outs to the most important new tools and developments of the last year. (Meanwhile, many of these new tools have been added to Pepperoni by the active contributor community.)
Libraries
- React Native (duh)
- Redux architecture following the Ducks pattern
- redux-observable for side effects
- redux-persist for offline caching
- react-navigation for navigation
- styled-components for UI styling
Tooling
- Yarn for dependency management
- Flow for static type checking
- Jest and Enzyme for testing
- Prettier for code formatting
- Storybook for component style guide
The Shouts
When I started writing this post, I didn’t realize what is now plain to see: except for Redux, none of these tools were part of my toolkit one year ago.
- react-navigation, though still in its early days, solves the previously lackluster navigation story beautifully, and works well with Redux.
- styled-components, while strictly speaking is mostly a syntactic improvement over the standard React Native styling, encourages small presentational components and more considered design systems in UI development.
- redux-persist has replaced my home-grown persistence solution, and now plays a central role in our Offline First architecture (more about that at React London).
- redux-observable is our answer to the question, “Which async redux middleware should we use?” It’s expressive enough to solve asynchrony and effects modelling without introducing accidental complexity (I’m looking at you, sagas), and the underlying RxJS 5 is faster and tighter than its predecessor. I have only begun to use redux-observable, but I already love it. (For full disclosure, our budding love story is something of a rebound; my previous partner, redux-loop, is going through a rewrite, and we need some time apart to see if we still want to be together.)
Surprisingly missing from this list is Immutable.js. While a great library, its bespoke collections API introduces too many challenges in interfacing with third-party code and serialization boundaries. If I feel we need development-time mutation-safety, I’ll reach for seamless-immutable, but for now we’re going with pure willpower and static typing.
Flow, the gradual static type checker built into the React Native packager toolchain is the biggest improvement in the last year. I can’t stress how important type checking is for creating maintainable, error-free javascript applications. While TypeScript might be more mature (and Flow certainly still suffers from growing pains), you can’t beat Flow for the seamless interop with the React Native ecosystem, including many of the third party libraries in our stack.
On the tooling side, Facebook Open Source is putting out amazing work beyond Flow. Yarn is a no-brainer. Faster, reproducible dependency management? Yes, please. Jest has seen massive improvements in the last year and is now the simplest React test runner out there. The jury is still out on the long-term effects of snapshot testing on codebase maintainability, so we still use AirBnB’s Enzyme for writing BDD-style UI test assertions.
Code style arguments used to be a big source of bikeshedding, but there’s no point arguing against the Prettier code formatter. The computer will always win, and it does not care about your feelings. We still use ESLint to supplement.
Finally, I can’t leave out React Native Storybook. A long-time best practice in web development, style-guide-driven design systems haven’t traditionally reached ubiquity in mobile development, perhaps because of the underpowered component systems in native SDKs. With React Native (and styled-components) there are no excuses not to build interactive pattern libraries on mobile. At Formidable, we take style guides seriously.
(You might ask, where’s Apollo or Relay? Or reselect and normalizr. All great tools, but I see using them as per-project choices to solve specific problems, not as part of “the stack”. If you think I’ve missed something crucial, let me know at @jevakallio.)
In Closing
This link dump represents my team’s best ideas on how to build mobile apps with React Native in March 2017. I look forward to reviewing this list in a year, and marveling at how far we’ll have come again.
Here’s a few more shout outs for all the amazing people in the open source community, creating libraries and tools, without which we’d have nothing.
And remember, there is much more to building great software than choosing your tools. Once chosen, they must be wielded with great precision and applied to a good cause: to create apps your users love, and your future self can look back to and feel a twinge of pride among the inevitable, “I can’t believe we used to do it like THAT back then.”