Code style is enforced using Prettier, ESLint and all the configuration provided by the packages in this repository.
See the dedicated TOOLING.md
documentation for more
information.
If you don't explicitly put the opening and closing markers on different lines, Prettier will try to format it the wrong way since it considers your component being an "inline" component (like spans), which results in something like that:
From
<!-- prettier-ignore -->
<MyComponent class={style.component}>Content</MyComponent>
Into
<!-- prettier-ignore -->
<MyComponent
class={style.component}
>Content</MyComponent
>
We see that we have weird break line characters, but this is the expected behavior, and the reason can be found here: https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting.
Until the point where prettier/prettier#5415 is
resolved, we can fix that by explicitly tell Prettier that our component is a
"block" component by adding a comment <!-- display: block -->
but that would
dramatically overload the source code, so the temporary solution is to be
carefull and to explicitly add new lines within the component markers and not
let prettier auto correct the component formatting. To take the same example:
This
<!-- prettier-ignore -->
<MyComponent class={style.component}>
Content
</MyComponent>
Becomes
<!-- prettier-ignore -->
<MyComponent
class={style.component}
>
Content
</MyComponent>
No more weird break line characters.
We are using single quotes ('
) in the codebase. Prettier and ESLint should
take care of this for you.
When you need to have single quotes inside of a string, you should use double
quotes ("
)
Also note that
you are not allowed to use backticks (`
) when the String Template doesn't hold any variable interpolations (${myVar}
).
Don't worry though. If you mis-used a quote, your linter will warn you, will auto-fix it for you on save and Prettier will auto-format everything for you too.
Always prefer using TypeScript over JavaScript.
This repository offers you all the toolings you need to use TypeScript in your application or package, so please use it to enforce type checking and make your code more reliable and self-documented.
Of course, you can configure/disable/extend the base TypeScript configuration at
the whole repository level
(using the tsconfig.json
file at root) or in each of your
packages/applications
(by adding a tsconfig.json
file in the appropriate folder and extending the base configuration with "extends": "<relative path to>/tsconfig.json"
).
When you want to use TypeScript in a package/application, you
will have to add typescript
as a development dependency.
To make the code easily redable and self-documentation, we need to ensure to use the proper conventions and right types as much as possible.
For examples, on a code like this:
if (isReady) {
// Do something.
}
We definitely expect isReady
to be Boolean
. Of course, in JS it could be
anything, but it is misleading for everyone. So here are the rules:
- A variable name starting with
has
oris
has to be a Boolean - The output of a condition (
if
,while
, ...) has to be a Boolean
A good practice is to use methods offered by Lodash to ensure some conditions.
❌
if (someArray.length) {
// Do something
}
if (someNumber) {
// Do something
}
if (someString) {
// Do something
}
// Careful, this is true!
const emptyObject = {}
if (emptyObject) {
// Do something
}
✅
import isEmpty from 'lodash/fp/isEmpty'
if (!isEmpty(someArray)) {
// Do something
}
if (someNumber > 0) {
// Do something
}
if (!isEmpty(someString)) {
// Do something
}
if (!isEmpty(emptyObject)) {
// Do something
}
When resetting a value or putting a default value to something, always try to
use null
instead of undefined
.
It does not make sense to specify an undefined value to a variable, right?
null
: has been declared & defined. Has simply no value.undefined
: declared but not defined.
undefined
will use the default while null
does not.
Also, extensively use the optional chaining operator ?.
to avoid undefined
and the nullish coalescing operator ??
to avoid null
.
We always want to keep track on what remains to do on the code base.
If you want to finish something later or clean part of the code, you just have
to add a TODO
associated with a ticket number and a small description as done
in the example. If you want to highlight a potential code smell that needs to be
fixed ASAP, you just have to add a FIXME
associated with a ticket number and a
small description as done in the example.
/*
* TODO [#1234]
* Define a proper error state in case of failure inside
*/
For a component-based architecture to be efficient, a component must have a clear responsibility.
It should be only responsible for its own logic, style and templating.
Readability makes a component easy to understand, to review and to re-use for
everyone.
This will also greatly improve the self-documentation of your code.
Here are a few rules to ease the readability:
- If you have a big block of logic in a JSX block, try to extract it into a function and call it instead;
- If you have a static value to use in your component, add it as a constant so
it's more explicit, adds context for the reviewers and is harder to remove it
accidentally.
You can also extract those constants in dedicated
constants.ts
files; - The same applies for your TypeScript typings. Always create a dedicated type
instead of inlining it in the code.
If those types are used in multiple components, you can extract them in
dedicated
types.ts
files;
If a condition/computation is repeated more than once in your component, create a function. This way, refactoring of the condition/computation will be easier.
You should arrange HTML attributes in this order and follow the alphabetical order:
data-\*
attributes (but try to avoid them as much as possible)- class
- standard attributes (i.e., props/attributes without JSX binding between
{}
) - bound attributes (i.e., props with JSX bindings between
{}
) - functions (e.g.
onClick
,onSubmit
, ...)