In order to improve the clarity, quality and development time it is worth considering the following principles whenever possible:
- DRY (Don't Repeat Yourself)
- KISS (Keep It Simple, Stupid)
- SoC (Separation of Concerns)
- Single responsibility principle
- Law of Demeter
-
Airbnb JavaScript Style Guide is partially being followed in our code base.
-
Code formatting is handled entirely by Prettier. Run
npm run prettify
from the root of the project to format all code. Code is also automatically formatted pre-commit. -
Check below for the rules that are not caught by ESLint but should be followed.
Variables: Variables should be lowercase words separated by _
.
const field_name = '...';
Functions: Functions should be camelCase. This is to easily distinguish between variables and functions.
const myFunction = () => { ... };
Modules: Module names and classes should be PascalCase.
const MyModule = (() => { ... })();
JavaScript elements: JavaScript elements start with el_
for a similar effect.
const el_test = document.getElementById('test');
Boolean: Those variables which store a boolean value, should start with is_
, has_
, ...
const is_updated = true;
const has_crypto = false;
Explanations: Feel free to add comments to explain any code that is confusing.
To do: Use TODO: [search-key] - {explanation}
comments anywhere that needs consideration or attention in the future. Please use a unique key per issue that a TODO addresses so that we can find all TODOs of similar nature by searching for the key.
API requests: Comments should be added to highlight logic that is hardcoded in the front-end and should move to API:
-
For changes that can be done in API V3, use the comment
// API_V3: [description of what needs to be moved to API]
-
For changes that should be done in API V4, use the comment
// API_V4: [description of what needs to be moved to API]
Require: Prefer import
in import statements.
Alphabetical ordering: The order is important; it should be sorted alphabetically according to path:
moment
comes first as it's not a relative path.s
is beforeu
so./storage
comes before./utility
.- Both
applyToAllElements
andcreateElement
are from the same file, buta
is beforec
- Unassigned
require
goes to the end
Imports are grouped by: 3rd-party first, then local absolute imports, then local relative
Combining require: When there are many functions being imported from the same file, consider combining it into one import line.
import React from 'react';
...
class ABC extends React.Component { ... }
...
React.useCallback(...);
React.useEffect(...);
...
- Use destructuring to capture parameters if needed.
- Use
{condition && <el/> ...</el>}
syntax to conditionally render an element. - Use
<el attr={value || undefined}
to conditionally render an attribute, React omits attributes with null or undefined values. - Use
localize('...')
or<Localize i18n_default_text='...'
for translations. - Use
website_name
constant instead ofDeriv
. - Do NOT use
<Element attributeName={true} />
; just use<Element attributeName />
. - Always name your components before default exporting them, for example:
import React from 'react';
const Loading = ({theme}) => (
<div className={`barspinner ${ theme || 'dark'}`}>
{ Array.from(new Array(5)).map((x, inx) => (
<div key={inx} className={`rect${inx + 1}`}></div>
))}
</div>
);
export default Loading;
- There are cases where you do not want your strings to be escaped (i.g. when you place
<a/>
tags inside a<Table />
). To bypass HTML escape, you can use theinterpolation.escapeValue
boolean property of the localizeoptions
param (under normal circumstances do NOT use this.):
localize('{{opening_tag}}Deriv App{{closing_tag}}', {
opening_tag : '<a href="https://app.deriv.com" rel="noopener noreferrer" target="_blank" class="link">',
closing_tag : '</a>',
interpolation: { escapeValue: false },
}),