# JavaScript, TypeScript
- Use TypeScript, Prettier, ESLint, and Jest. Add
prettier
andeslint
plugins to your IDE. - ESLint must include rules:
airbnb
,prettier/react
,prettier
,plugin:react-hooks/recommended
.
# React.js
# Naming
Folder structure example:
SmartTable/
SmartTable.tsx
SmartTable.spec.tsx
styles.scss
constants.ts
reducer.ts
reducer.spec.ts
thunks.ts
thunks.spec.ts
models/
schemas/
Thead/
Thead.tsx
styles.scss
TH/
TH.tsx
styles.scss
- The directory structure corresponds to the DOM structure.
- Folders that contain collections wrote in lowercase. Example,
models
. - Write component file in camel case starting with capital symbol. Example,
SmartTable.tsx
. - Component name must be a noun. Example,
InvoiceTable
. - Use camel case for variables, i.e.
userName
. - User pascal case for classes, types, interfaces, components. Examples
UserPage
,Campaign
. - Use upper case for constants. Examples
CACHE_TTL
,COUNT_LIMIT
. Prefer to them inconstants.ts
file.
# Application layers
- Component subscribes to redux state, dispatches events to redux, and calls redux-thunks. It can have some UI-related
state (i.e., form values). Do not use
useReducer
hook. - Redux-thunk handles the side effects of actions (e.i., fetches data from server, handles exceptions).
- Reducer is the business logic layer.
- API raw data acquisition layer (json). Convert the keys to camel case using
convertToCamelCase
function:
# Components
Use
React.FC
(React.FunctionalComponent
) and hooks instead of classes.Avoid HOC (High Order Component) and render props patterns. Prefer decompose components or using Contexts.
Make Component's API clear and simple. Pass only minimal necessary props.
Use proper props order:
- Required props.
- Optional props.
- Required callbacks.
- Optional callbacks.
Store all business logic on a single layer. You may create a context for that:
Name boolean properties without
is
, i.e.disabled
,checked
,searchable
.Extract all variables
variables.scss
file.Store component styles in
styles.scss
file. Avoid creating multiple files in one folder.
# Re-export (index.ts)
- Use when you need to export a collection of elements, i.e. components, types, redux actions.
- Use when you need to export several entities from a complex component. E.g.: the component, and types
# Stylesheets
- Enable stylelint with the following plugins:
stylelint-config-standard
.stylelint-config-standard-scss
.stylelint-config-sass-guidelines
.
- Prefer SCSS with CSS Modules. Default file with the is
styles.module.scss
. - Avoid CSS-in-JS, Styled, Tailwind and other CSS-In-JS libraries.
- Prefer SASS variables.
- Prefer using measures in
em
orrem
:- If you need to strictly observe the dimensions, then use
rem
. - If the dimensions are adapted, then use
em
. - The pixel unit
px
is used in extreme cases. For example, when we use inline styles (although we try to avoid them completely and use selector classes).
- If you need to strictly observe the dimensions, then use
- Keep classes lowercase and use dashes (not underscores or camelCase). Dashes serve as natural breaks in related
classes (e.g.,
.btn
and.btn-danger
). - Avoid excessive and arbitrary shorthand notation.
.btn
is useful for a button, but.s
doesn't mean anything. - Keep classes as short and succinct as possible.
- Use meaningful names; use structural or purposeful names over presentational.
- Prefix classes based on the closest parent or base class.
# Contexts
- Use only for immutable data. Do not store business logic here.
# Memoization
- Avoid using memoization if there are no performance issues.
- Use
Highlight updates when components render
to check how ofter components rerender. - Use
React.memo
if props don't often change, but the component has some heavy calculations. - Use
React.useMemo
to memoize some calculations. - Use
React.useCalback
if you want to avoid rerendering heavy child components.
# Typescript
- Prefer
type
overinterface
. - Use type inheritance only if new component is inherits a more than 50% of properties.
- Export types only if you want to use them in multiple places.
- Store reusable
types
store inmodels/
folder. - Do not add typing when TS interpolates automatically.
- Avoid using prefixes in type names like
T
,I
,Type
, etc. - Use singular type for enum types (e.g.,
State
,Language
)
# Tests
- Use Jest.
- Name a test suite file according to what it tests, i.e.
ComponentName.spec.tsx
orreducer.spec.ts
. - Cover with tests business or complicated logic.
- Use
describe
andit
:
describe("withdraw()", () => {
it('fetches API', () => {...})
it('dispatches specific actions', () => {...})
});
# Redux
- Use Redux on complex applications only. If Redux is installed, we avoid using
useReducer
hooks. - Use redux-thunks (opens new window) as side effect middleware.
- Read very carefully official Redux Style Guide (opens new window). Some highlights from
that guide:
- Model actions as events, not setters (e.g.,
dataFetched()
,windowClosed()
). - Only signle redux store per app.
- Do not mutate the state.
- Put as much logic as possible in reducers.
- Organize state structure based on data types, not components (e.g.,
{auth, campaigns, domains, users}
).
- Model actions as events, not setters (e.g.,
- Remember to clean the data in the Redux store.
- Prefer to use more generic values. For example, send a specific
{payload: FormPayload}
, instead of{name: string, address: string}
. - Store selectors fuctions in
selectors.ts
file:- To get data from redux, use the selector functions and store them in the file (selectors.ts) of the corresponding reducer.
- For selectors with complex logic, use a library redux-thunks (opens new window)
# Redux-thunks/ Api functions
- names of thunk function must mean action and must start with the verb. Example,
createUser
,fetchUsers
,deleteUser
,updateUsers
etc. - names of api function must start with the verb
request
. Example,requestUsers
,requestCreatingUser
,requestDeletingUser
,requestUpdatingUser
etc. - avoid using
import * as
instead, useimport { createUser } from './usersApi'
.
# Redux debugging
- Install Redux Dev Tools (opens new window) for Chrome.
- Third-party hook
useWhatChanged
helps to watch state changes. Example:
# Vue.js
Official Style Guide (opens new window)
- All projects are deployed using the Vue CLI. We use the file-base structure that the CLI provides by default after installing the project for small projects.
- If you understand that your project will be large, you can use a fractal structure (Module-based).
- We create component files in Camel Case style according to the official [style guide] (https://vuejs.org/v2/style-guide/#Component-files-strongly-recommended).
- It is preferable to use [Vue Class Component] (https://class-component.vuejs.org/) and TypeScript in the projects. Vue CLI allows you to enable this functionality when you install a project.
- Use standard ESLint rules from Vue CLI.
← Git Subtrees PHP →