This project aims to be a strong foundation for every new react-native application. It provides a clear and organized structure, core dependencies, and boilerplate to jumpstart development.
Click the "Use this template" button above the file list, then "Create a new repository". Creating a repository from a template has the following advantages:
-
Creating a repository from a template is the fastest way of starting a new project.
-
A repository created from a template starts with a single commit.
-
Commits to a repository created from a template show up in your contribution graph.
On the new project, use react-native-rename to set the desired project's name. Just run the script, delete your node modules and reinstall them and you should be good to go.
Disclaimer: In the current state of this project, it should give you no issues at all, but keep in mind that this library can cause trouble if you are renaming a project that uses Pods
on the iOS side.
After that you should proceed as with any React Native project:
- Go to your project's root folder and run
npm install
. - Run the script defined in the package.json file to install ios dependencies:
npm run pods
- Run
npm run ios
ornpm run android
to start your application!
Note: Please read the Setup environments section for more information about the execution scripts.
If you want to roll on your own and don't want to use Reactika as a template, you can just create a new project using npx react-native init
(or npx create-expo-app
) and then copy one by one the /src
folder as well as the configuration files.
Keep in mind that if you do this, you'll have to install all the dependencies (as well as the corresponding native code for each of the libraries that require it).
If your preferred package manager is npm then you are good to go, the package-lock.json
is already commited in the project and github workflows are using it too for caching.
In case you prefer yarn, that's fine too! Steps to follow are:
-
Delete
package-lock.json
file -
Run
yarn install
and make sure to commit the newly createdyarn.lock
-
In the
./github/workflows
follow the steps in thecodeQualityCheck.yaml
file to start caching with yarn. Caching is crucial to reduce the load on GitHub's runners by storing and reusing dependencies during runs.
The project comes with dev
, stg
and prd
as the default environments. If your project needs others, just read through this section and make the required changes on the native projects.
The template also comes with pre-defined scripts to run the project in debug/release. Keep in mind that if you create new envs
you need to adapt them to build the corresponding new environments.
To define which env you want to use, just follow the structure npm run [platform]: [environment]
e.g: To run a dev build in debug run: npm run ios
or npm run android
Environment variables for the JS side, are defined on a per-env basis, in different files. Find these in the root folder (.env.development
, .env.production
and .env.staging
)
The environemnts were mapped 1 to 1 with Android flavors to setup the variants on this platform. A map associating flavors with env files is already defined in app/build.gradle
. Modify or add your own environments if needed.
Disclaimer: For multiple enviroments to work you will need to update your proguard-rules.pro
file with the name of your project's main class.
-keep class [YOUR_PACKAGE_NAME].BuildConfig { *; }
The environments were mapped 1 to 1 with Schemes (And their corresponding target) on iOS. Each scheme has the corresponding environment file associated, so you can easily alternate between them. The role of the targets is to hold any specific native configuration and pick up environment specific files (Such as the Firebase GoogleServices-Info.plist
)
To create a new scheme:
-
In the Xcode menu, go to Product > Scheme > Edit Scheme
-
Click Duplicate Scheme on the bottom
-
Give it a proper name on the top left. For instance: "qa"
-
Then edit the newly created scheme to make it use a different env file. From the same "manage scheme" window:
Expand the "Build" tab on the left menu
-
Click "Pre-actions", and under the plus sign select "New Run Script Action"
-
Where it says "Type a script or drag a script file", type:
echo ".env.qa" > /tmp/envfile
replacing.env.qa
with your file. -
Also, you will need to select the executable for the new schema:
Expand the "Run" tab on the left menu
- Under the "Executable" dropdown select the ".app" you would like to use for that schema
The template approach is separating the js
env variables from the native
ones.
- The first should be written into the
.env.[ENVIRONMENT]
files, likeAPI_BASE_URL=XXX
.
API_BASE_URL=XXX
- The latter should be written directly on the native config files each platform provides, for example the
Info.plist
(iOS) files orres/values/strings.xml
(Android).
<!-- Android res/values/strings.xml -->
<string name="app_name">YourAppName</string>
These are the steps to generate .aab
or .apk
and .ipa
files, using Fastlane, a Ruby open source tool.
- Install dependencies using bundler:
bundle install
-
Generate an upload key for signing the release build
-
Set up gradle variables as explained in Environments
-
Execute
fastlane android build[Type][Output]
Note: Type
in [Dev, Staging, Prod]
and Output
in [APK, AAB]
For more info please about generating the key refer to Official Android Release Process
-
Create and download an Appstore Connect API key.
-
Fill in
APP_STORE_CONNECT_API_KEY
properties in thefastlane/.env.default
. -
Fill in the TEAM id values, for team id and itc team id in the
fastlane/.env.default
. -
Execute
fastlane android build[Type]
Note:
Type
in[Dev, Staging, Prod]
For more info please go to Official iOS Release Process
The suggested architecutre follows the ideas discussed in Elegan FE Architecture, but the main responsabilities of each high-level folder are:
-
src
: This folder is the main container of all the code inside your application. -
ui
: Holds every visual component specific to your application. Custom styling and atomic components should live here, but not anything specific to your domain like "a list of users", only a "card" or "label". -
infrastructure
: Holds generally useful elements to your application, that support it in its function. The api and authentication submodules are set-up as prominent examples of this. State management (e.g. the redux store) also lives here. -
application
: Is the owner of your lifecycle and in charge of navigation. This module is the most specific to your app in terms of a "mobile executable", and cares the most about the device you might be running on, and the direct interaction with the user. -
features
: Is composed of submodules that fully contain all of the business-centric aspects of your application. Many examples are set up on the boilerplate of different possible usecases, but it is impossible that any "domain" submodule can be generally enough to be included in a boilerplate. Each domain can export, in its index file, components or reducers that can be bound to your Redux store or to one or more screens for its use.
Reactika tries to solve the basic Authentication setup that most apps need.
For this purpose, it provides SessionContext
and SessionProvider
. These two expose logIn
and logOut
methods which encapsulate the logic to call the authentication api, and they also provide some useful info regarding the status of the authentication process (isPendingLogIn
, logInError
, and an isAuthenticated
flag).
This implementation already handles the api setup too. This is done by setting up two interceptors:
- For outgoing requests, which injects a "Bearer Token" type
Authorization
header. - For incoming responses, which logs out the user whenever a 401 code
Unauthorized
is received.
Although this behavior is relatively common, your use case could be different, in which case you can customize the behavior by messing with the useSetUpTokenWithAPI
and useAPIConfig
hooks in the SessionProvider
.
Redux toolkit has been setup as the default global state manager. It already contains one slice, the session
slice, to hold the data related to the authentication of the user.
Notice that this slice is persisted using EncryptedStorage
for higher security, while the others slices can be persisted with the standard AsyncStorage
.
The library used to localize the strings of the app is react-native-localization
.
For dates managament Reactika uses date-fns
and thus in case your app supports a new language, you will have to add the corrresponding "locale" for it in the languages file.
Disclaimer: If the device's language is not supported by your strings files, the first language in the languages
object will be used.
A creator function is implemented to centralize and simplify the creation of Text components.
Create a new one by following these steps:
-
Using StyleSheet, create a style inside
src/ui/text
folder -
Declare and create a new text component by using the
makeText
creator function, with the style just created -
Add your component to the
text
module exports -
Import it from anywhere inside the Navigator's scope and use it
Note 1: styles are applied to the custom Text component following this order
-
Theme: The theme's colors.text is applied first as the default color
-
The style passed during the component declaration
-
The style passed to the component when using it.
Note 2: You should not use raw text inside these components (eslint will prompt you about this). Instead, you should use constants/variables that contain the text you would like to display, like so:
// ... component
const foo = 'bar'; // constant that contains the text displayed
// Suppose H1 is a text component
return <H1>{ foo }</H1>;
Custom fonts can be easily added to the project following the standard process. A custom font was added as an example using npx react-native-asset
.
Steps to add a new one:
-
Add font file to the
assets/fonts
folder. OTF format is preferred. -
Run
npx react-native-asset
to link the fonts to the native projects -
Rebuild the app to load the custom fonts in your app
Read this guide to learn more about how to configure custom fonts