I've been working with React Native for about 3 years now. I've built applications mainly for small businesses and entrepreneurs as a freelancer during this time. As the months go by, I find myself using pretty much the same architecture again and again.
My coding has been influenced heavily by Laravel's framework principles as well as "Clean architecture" from Robert C. Martin. One of the core principles I follow is loose coupling. As I work mostly alone, it allows me to quickly replace modules I've implemented for another one.
The most important files for me are the following:
config.js, These reside mostly at the root of the project folder. I consider
index.jsas the loading logic. I rarely modify it from the default that is generated when creating the project using
App.js Is the super container. It represents the root of the React root and it is where I integrate any React Native library that deals with context, like Theme, Navigation and Redux. It is the only React files that depends on non-react modules.
I seldom use a config file. It mostly reserved if I have constants in the business logic that can be modified later or any temporary service configurations.
react-navigation library has been enough for my needs so far. I usually configure it inside one file name
navigator.js. It is the interface between the screens and the main App component. It does not handle navigation logic, just the configuration.
I'm a big fan of the functional paradigm. Now I'm using functions for every React components I write. I think it is better for handling side effect from a readability point of view. My preferred method is using files directly like
Screen.js instead of
Screen/index.js I've seen people do. Styling is written at the end of the file and I use flow for specifying the type of the props.
Screens are the main containers or smart components. That is where I write business logic and side effect code (like asynchronous code that deals with services). The UI is handled mostly by the components.
Most of the components are dumb. They display data or accept input from the user and hand out the result to the main container. They follow the same template as screens. I often write component in the same file of the screen that will host them (Row in a list). But reusable ones are stored under the
components subfolder of the project.
Services are for everything that interacts with the outside world. REST API, BaaS, Persistent Storage, ... all fall under that category. The key is to decouple the service from the main code. Apart from that file, there shouldn't be any mention of the service anywhere else (Apart from
config.js). It is mostly the configuration logic that will be inside the file and a collection of functions to use elsewhere.
These are small functions that contains logic you find yourself reusing throughout the app. Things like concatenating the first name and last name of the user, formatting strings, calculating various values... I just group them by category (
format.js) and put them inside a
This is an optional one. I mostly use Redux for caching API responses. It permits me to go from an asynchronous paradigm to a reactive one. I found myself not using it with Firebase and Apollo GraphQL as the latter ones have their own caching mechanism. When I do use Redux, I used the
rematch library is it eliminates a lot of the boilerplate.
These deserve their own section. The most notable examples are theming and localization libraries. They do not deal with the outside world but are important enough to not be relegated to the
util folder. They are mostly stored alongside
App.js as they will be integrated there.
This is my own internal template that I use when writing React Native app. There is not a linked GitHub repository as I modify parts of it when I'm working on a project depending on the requirements. It helps me switch whatever I want easily as the tight coupling is restricted to a few locations, everything else is connected together by conventions. Do you use something similar in your own React Native project?