-
Notifications
You must be signed in to change notification settings - Fork 2
Modular system
Modules contain application code split by features. For example, all countries' related code is placed in the countries
module. Every module must have exactly one declaration file - index.ts
. This file lists all module exports that are available for use in other modules. Modules can also declare their types (types.ts
) and configuration options (config.ts
).
The rest of the module's code is split into sub-modules. Available sub-modules are: __mocks__
, components
, hooks
, screens
and services
. A module must contain at least one sub-module and can contain all sub-modules.
For example, consider the countries
module. This module contains all allowed submodules and it's structured in the following way:
./countries
----| __mocks__
----| components
----| hooks
----| screens
----| services
----| config.ts
----| index.ts
----| types.ts
File config.ts
contains constants and configuration settings of the module. It can be used throughout the module itself and is also exported to use in other modules.
config.ts
example:
export const SOME_VALUE = 10;
File index.ts
defines all exports available in other modules.
index.ts
example:
export * from './components';
export * from './hooks';
export * from './services';
export * from './screens';
export * from './types';
export * from './config';
File types.ts
contains all the types related to the module. It can import types from other modules and it also exports types to be used throughout the module itself and in other modules.
types.ts
example:
export type SomeType = 'value1' | 'value2';
This is the place for react-native components related to this module. Every component is placed in a separate directory. The directory name is capitalized, camel-cased name of the component. All the assets, styles, and tests related to the component are placed in the same directory. The component code itself is in the index.tsx
file of the given component and it's exported by default. Apart from the "main" component, the component directory can also contain helper components. These are not meant to be exported from the module, but they can be used to split larger components into smaller parts.
components
sub-module example:
./components
----| SomeComponent
----| AnotherComponent
SomeComponent
component files structure with InternalComponent
helper component:
./components
----| SomeComponent
----|----| __tests__
----|----| InternalComponent.tsx
----|----| image.png
----|----| index.tsx
----|----| styles.ts
Contains all module-related custom hooks. Every hook is placed into its own file and the filename must start with use
. For example useSomeInformation.ts
. Hooks are exported from their files as default exports. Apart from hooks, this submodule also contains an index.ts
file that exports available hooks.
hooks
sub-module example:
./hooks
----| __tests__
----| index.ts
----| useSomeInformation.ts
----| useAnotherInformation.ts
index.ts
for this example would look like this:
import { default as useSomeInformation } from './useSomeInformation';
import { default as useAnotherInformation } from './useAnotherInformation';
export { useSomeInformation, useAnotherInformation };
Contains all navigation screens of the module. Every screen is placed into its own folder. The folder name is capitalized, camel-cased name of the screen. This folder also contains tests and styles for the given screen.
screen
sub-module structure example:
./screens
----| SomeScreen
----|----| __tests__
----|----| index.tsx
----|----| styles.ts
----| AnotherScreen
----|----| index.tsx
----| index.ts
This screens would be exported from sub-module's index.ts
file in a following way:
import { default as SomeScreen } from './SomeScreen';
import { default as AnotherScreen } from './AnotherScreen';
export { SomeScreen, AnotherScreen }
Contains various module-related services: APIs, parsers, utilities, initializers, and so on.
Every service is placed into a separate file. The filename of the service consists of the lowercased module name and service type. Eg.: someApi.ts
, someParsers.ts
etc.
services
sub-module example:
./services
----| __mocks__
----| __tests__
----| someApi.ts
----| someParsers.ts
----| index.ts
The exports from sub-modules index.ts
:
import * as someApi from './someApi';
import * as someParsers from './someParsers';
export { someApi, someParsers };
There are few simple rules for importing code depending on where does the import comes from.
The simplest case is an import of 3rd part code from a node_modules package:
import React from 'react';
import { View } from 'react-native';
Another possibility is the import of code from the same module. In this case we use relative path and we import the whole needed sub-module:
import { someApi } from '../../servies';
import { useSomeInformation } from '../../hooks';
The next option is importing code from the same module and same sub-module (eg. from one module's component into another). In this case, we use just plain relative import:
import SomeComponent from '../SomeComponent';
import AnotherComponent from '../AnotherComponent';
And last option is the import of code from one module to another. These imports can only import parts declared in the index.ts
file of the module that we want to import and they use an alias:
import { SomeComponent, useSomeInformation, someApi } from '~modules/someModule`;