Technology

Kristina Vragovic

Bringing Rails Convention to the Wild West of JS

Aug. 22, 2018

Necessity is the mother of invention — but Rails is the mother of convention. And sometimes, what you really need is some structure.

Here at 20spokes, we have branched into mobile in a big way, using React Native with Rails APIs. As a consultancy, we have the unique perspective of building projects from scratch often, and we kept coming back to folder structure. Namely, how on earth does anyone find anything in a React Native (or React.js) app as it grows?

Most of the React tutorials we saw out there had three main folders for their files: elements, modules, and components. (Redux projects will sometimes expand that to include an actions folder.) But try getting someone to actually define what an element is, versus a module, versus a component, and the argument quickly becomes circular. Elements are reusable, they say. Well, so are modules. Modules are bigger, though. Sort of.

So we decided to write our own rulebook. Trash it if you like, but it’s worked pretty well for us so far, and going back to maintain projects we built before we established this style? The difference is mind-boggling.


    |_ __tests__
      |_ ...mirrors the src folder
    |_ android
    |_ assets
    |_ ios
    |_ src
      |_ actions
      |_ contexts
        |_ Profile
          |_ modules
            |_ AvatarUploader.js
          |_ views
            |_ EditProfileView.js
            |_ PublicProfileView.js
          ProfileStyles.js
      |_ elements
        |_ Buttons
          |_ ButtonPrimary.js
          |_ ButtonSecondary.js
      |_ helpers
      |_ layouts
      |_ navigators
      |_ utils
    App.js
    index.js

Along with this folder structure, we’ve employed babel-plugin-module-resolver to help with the dreaded strings of ../../../../ before import statements. That way, every time we need a common element in a view within the contexts folder, the import path can be as simple as elements/Buttons/ButtonPrimary.js. Learn more about that plugin here — it’s been key to our success with this structure.

Putting it into contexts

If you’re building any kind of mildly robust mobile application that makes requests to an API, you probably have several "flows" through the app. Settings. Login. Feed. Profile. Onboarding. Any "section" of the app that you’ve probably already chunked out as a feature set is probably also a context. We decided to create a folder for each of these contexts, with all the views in that context along with all of the modules/elements that are particular to that context. [1]

For example, a public profile view, an editable profile view, and an avatar uploading module would all be in a Profile context folder. If an element is reusable outside of that component, stick it in the elements folder instead. The contexts folder was the real heavy-hitter in our redesign. You’re welcome.

Let me lay it out for you

Most of the apps we create have custom navigation bars/drawers or SafeArea wrappers that need to go on every page. We usually call this a ViewWrap.js or TopNav.js, whatever the use case is. Sometimes different kinds of views have different view wraps. The layouts folder is for these — just like in Rails.

Check the GPS

The navigators folder is a handy place for all your navigation-related files.

If you’re familiar with navigation libraries for react like React Navigation, you know that each app "flow" needs a navigator file or something like it. We used to keep these in the junk pile, AKA the top level of the folder structure along with App.js and index.js. But for complex apps with lots of form flows, or different user journeys, having a navigators folder — with subfolders like Admin or Onboarding or other, more specific navigational needs — makes it a lot easier to grok the app’s navigational complexities.

Going off the Rails

As a software consultancy, we have a particular interest in making sure that our code is easy to read and maintain by another team sometime down the line. But let’s be honest — we’ve all read a codebase that we wish had been written with future developers in mind.

Going back to old projects, ones built before we adopted this new folder structure, isn’t a total nightmare (we have always been pretty good at this readability stuff, after all). But it truly is amazing how much of a difference the new structure has made. No longer do I have to wonder which Events folder is going to have EventCard.js in it — src/elements/EventCard.js or src/modules/EventCard.js? There’s only one Events folder, src/contexts/Events. Something reusable like a card will maybe be another folder deep, in a modules folder particular to events. But that’s it. No more digging!

Even if you decide not to implement our folder structure for your next React or React Native project, what I hope you’ll take away from this success story is that it’s invaluable to consider lessons you’ve learned from other frameworks. What makes Rails infinitely easy to jump into and know where to look for things is totally doable in React. So get after it!

[1] We did not know that React 16.4.2 was about to come out with this Context thing. Sorry for any confusion. Call the contexts folder whatever you want?

Kristina Vragovic

What People Are Reading

Technology

11/20/17

Cross-Platform mobile development is cost-effective and faster to launch

Two years ago, if a person approached us for mobile app development, the first question would be what platform to launch on first - iOS or Android. It was almost double the cost to deploy on both and double the maintenance.

Fast forward to today, we can deploy on iOS and Android quicker before, at the same time, and with the expected native quality.

So what has changed? Technology has gotten a lot better. We particularly use React Native, an open source framework from Facebook, that allows developers to develop in a common language, Javascript, and deploy on both iOS and Android.

And it is native! Previous technologies for cross platform mobile apps would create a wrapper of a web view. Think of the older experience as using the browser on your phone for a site with a few more bells and whistles. It was close but the difference is noticeable when switching to native applications, from scrolling to the overall experience.

How does this impact everything now?

Cost is no longer double for both platforms. It can even cost less due to wide spread community support developing open source libraries.

Maintenance is a lot easier. A majority of the issues can be fixed in one code base and of the same language.

Recruitment and team knowledge is easier. Your team only need to know one language and most developers know Javascript. iOS is written in Objective C or Swift and Android is written in Java.

Reusable code for desktop web views. With React Native, we are able to share over 50% of the code with the web view, saving all of the above even more.

Stay tuned, as I’ll be going more into the technologies and other benefits.

Operations

8/29/16

Watch us eat our own dog food

20spokes is trying a new diet, so to speak. If you’re unfamiliar with the phrase “eating your own dog food,” it’s a common expression in the software world referring to a developer’s practice of using their own products. It’s said to have originated from 1970s television advertisements for Alpo dog food, where the owner of the company would make a point of feeding Alpo to his own dogs. So in its broader interpretation, “practice what you preach” would be an appropriate alternative. Either way, if we can help others build great products, we want to show that we can build our own great products as well.

It’s something we’ve thought about for a while, and now we’re finally taking the steps to make it happen. Client work will still always be our primary focus, but we have the team, the experience, and the aspirations; why wouldn't we work on our own ideas too? Like our clients, though, we don't want to jump into these ventures haphazardly only to end up with a well built app that nobody else wants. So we're putting these ideas through the same process of discovery, validation, and planning that we would with anyone who came into our office. In a way, by becoming clients of our own process, we’re getting our first helping of dog food!

Over the last week or so, we’ve adopted the mindset of a founder with a vision, and taken one of our ideas through the first steps of conception. Working through this process as the “founder” has already given us some great new insight, and we're excited to share this journey with you. So stay tuned for the next several weeks as we document all the steps we take and lessons we learn along the way; we're going to find out just how good our dog food tastes.

Trying to get your own product idea to market? Contact us to learn more about our process and how we can help.