# JavaScript, TypeScript

  • Use TypeScript, Prettier, ESLint, and Jest. Add prettier and eslint 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 in constants.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 or rem:
    • 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).
  • 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 over interface.
  • 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 in models/ 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 or reducer.spec.ts.
  • Cover with tests business or complicated logic.
  • Use describe and it:
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}).
  • 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, use import { createUser } from './usersApi'.

# Redux debugging

# 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.