Segment
Segment - the third level of application partitioning, according to the purpose of the module in the code and implementation
{layer}/
โโโ {slice}/
| โโโ ui/ # UI-logic (components, ui-widgets, ...)
| โโโ model/ # Business logic (store, actions, effects, reducers, ...)
| โโโ lib/ # Infrastructure logic (utils/helpers)
| โโโ config/ # Application configuration (env-vars, ...)
| โโโ api/ # Logic of API requests (api instances, requests, ...)
General rules
Each of the above segments represents the levels of abstractions that are familiar to us when developing software.
Each of the segments is responsible for its own scope, but all together - they form a single image of this slice and its logic, specifically:
- its visual display (ui)
- its business logic (model)
- its auxiliary modules (lib)
Also, in rare cases, affecting:
- its configuration (config)
- its logic for working with API requests (api)
tip
Each segment can be either a file or a directory - it depends on the complexity of the slice being implemented
That is, such options are also quite acceptable:
features/wallet/add-funds
โโโ ui.tsx
โโโ model.ts
โโโ index.ts
pages/home/
โโโ index.tsx
โโโ style.module.scss
ui
UI representation of the module
It can contain inside:
- Components of your UI framework (React, Vue, Angular, ...)
- Canvas-Widgets
- (any other ui view modules)
Examples
Complex UI for the layer
{layer}/{slice}/
โโโ ui/
| โโโ toolbar/
| | โโโ title/
| | โโโ actions/
| โโโ content/
| | โโโ sort/
| | โโโ table/
| โโโ index.tsx/
import Toolbar from "./toolbar";
import Content from "./content";
import styles from "./styles.module.scss";
export const SomeForm = () => (
<Layout className={styles.root}>
<Toolbar className={styles.toolbar} />
<Content className={styles.content} />
</Layout>
)
model
Business logic of the module
May contain:
- The logic of creating and updating a mini-store for this slice
- In the effector world:
createStore
+createDomain
- In the redux world:
createSlice
- In the effector world:
- A list of events processed by the parent slice model and updating its state
- In the effector world:
events
- In the redux world:
actions
+dispatch
- In the effector world:
- List of asynchronous side effects, for loading data and other asynchronous operations
- In the effector world:
effects
- In the redux world:
thunks
/sagas
/epics
- In the effector world:
- List of selectors/contracts/hooks for using the slice state
- In the effector world:
useStore
, ... - In the redux world:
useSelector
,selectors
- In the effector world:
lib
Auxiliary libraries
It usually contains a set of utilities that help writing logic and are distributed in groups, i.e. separate libraries.
api
Logic of interaction with the API
Usually contains
- instances for working with different external APIs
- methods / factories for calling specific endpoints
In rare cases (react-query / graphql), the queries themselves may lie near the place of use
- But most often recommended place the API segment in the 'shared' layer to reduce the number of logic entanglements
At the same time, this segment can be written manually or generated using the API scheme
- For example, using
openapi-generator
,swagger-codegen
Examples
export class UserApi {
constructor(config) {...}
getList(params: GetListParams): Promise<User[]> {...}
...
}
import { userApi } from "shared/api"
// API instances can be created
// both at the place of use and in the API segment itself
//
// const userApi = new UserApi();
export const getUserListThunk = createAsyncThunk("...", (params) => {
return userApi.getList(params);
});
config
Application configuration module and its environment
It usually contains the application configuration and methods for working with it
Examples
Using environment variables
The implementation depends on the project and the team, here is just one of the options
export const isDevEnv = NODE_ENV === "development";
export const OAUTH_TOKEN = getEnvVar("REACT_APP_OAUTH_TOKEN");
import { OAUTH_TOKEN, isDevEnv } from "shared/config";
export const OAuthProvider = () => (
<OAuth
debug={isDevEnv}
token={OAUTH_TOKEN}
...
/>
)
See also
WIP:
Over time, articles on each abstraction will appear