Front End
This page contains hints on how to write readable code, also known as Coding Style guidelines.
It "doesn't" mean you need to strictly follow the guidelines, the efficiecy is also as important as maintenance
For old projects, any refactoring work is welcome as long as it causes no side effect
Feel free to give any opinions/questions
Naming Conventions
Don't overuse short syntax and/or abbreviations.
Make the code easy to read and understand. Make it communicative,
even if that means it will be more verbose and take more time and effort to write.
This also applies to naming of files and directories!
const hasDevelopers = project.id && project.developers.length !== 0;
if (hasDevelopers) {
//doSomething()
}Remove or comment the console before pushing to Gitlab
consoleis often used to show data when develop/debug ...etc,after finishing the job it should be removed/commeted since the other developers will not know wheather to do so,
unless it is sure to be helpful such as error handler it may cause a great pollution as time goes by
Write functions with declarative names. Anonymous or not, it doesn't matter. As long as it describes it purpose with prefixes such as
get,set,create,delete, etc.Try to follow the JavaScript naming convention best practices. Credits to the article about the naming convention best practices.
- Constants -
UPPERCASE
const SECONDS = 60;
const MINUTES = 60;
const HOURS = 24;
const DAY = SECONDS * MINUTES * HOURS;They should always stay in the global scope. To avoid the function computing overhaust or wasting the memory dump. This way is also easy to navigate when reading the code.
- Variables -
camelCase
const firstName = "Matt";- Variables used by browser, e.g. input fields -
kebab-case
<input name="variable-name-in-kebab-case" />- Variables stored in the API, in the JSON -
snake_case
{
"machine_id": "randomId12345",
"machine_name": "Awesome machine name"
}- CSS style class names -
snake_case
.component_name {
display: flex;
}Reasoning: Syntax consistency and easier to use without using the neccessity to quote it, like:
const classNames = clsx(CSS.component_name, CSS.error);Instead of:
const classNames = clsx(CSS["component-name"], CSS.error);- Boolean -
camelCaseand with one of the following prefix:is,are,has
const isVisible = true;
const areEqual = false;
const hasEncryption = true;- Functions -
camelCase
function getName(firstName, lastName) {
return `${firstName} ${lastName}`;
}- Classes -
UpperCamelCase
class SoftwareDeveloper {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}- Methods -
camelCase
class SoftwareDeveloper {
getName() {
return ( ... );
};
}- Components (in any framework) -
UpperCamelCase
const UserProfile = (props) {
return ( ... );
}- Interfaces/Types (TypeScript) -
UpperCamelCase
type MachinData {}
interface MachineTableProps {}- Constants -
React
General
Functional component instead of Class compoenet
const MachineList = ({ machines }) => {
//...
return (
<Fragment>
{machines.map((machine) => (
<MachineItem machine={machine} />
))}
</Fragment>
);
};Prevent directly passing setState as a prop
//bad ❌
<SomeComponent onChange={setState} />//good ⭕️
<SomeComponent
onChange={(newValue) => {
setState(newValue);
}}
/>Organize imported modules in the code. This way we can visually see which modules are ours from this project and which ones have been imported from
node_modules/or Node.js built-in modules.import { useState } from "react";
import moment from "moment";
import { SomeButton } from "src/components/atoms";
import { SomeForm } from "src/components/organisms";
Types
Define interface as props instead of type
//bad ❌
type MachineTableProps = {};//good ⭕️
interface MachineTableProps {}Avoiding FC/ FunctionalComponent and Directly Using SomeComponentProps
export interface SomeComponentProps {
name: string;
}//bad ❌
export const SomeComponent: FC<SomeComponentProps> = ({ name = "" }) => {
return <div>{ name }<div>;
};//good ⭕️
export const SomeComponent = ({ name = "" }: SomeComponentProps) => {
return <div>{ name }<div>;
};
Project Structure
Organized by using Atomic Design.
Every project may have different packages/frameworks, but basically they followed Atomic Design (especially new project)
For better testing, they are split into two sub-categories in terms of usage:
- those which use API data :
templates&pages - those which use mockup data :
atoms,moleculesandorganisms
- those which use API data :
Name a component with common suffix to describe the functionality (declarative name)
suffix examples:
**_Form
_**Item
**_List
_**Card
**_Board
_**Page
\*\*\*Screen
const MachineList = ({ machines }) => {
//...
return (
<>
{machines.map((machine) => (
<MachineItem machine={machine} />
))}
</>
);
};
Sub-category by functionality
Based on Atomic Design, a reusable component shouldn't be designed for only one page/component
even if it's in fact useless for other pages
That is, it's not recommanded to put component into sub-category named by route/pageshould be
organisms
|_ forms
| |_UserLoginForm.js
| |_MachineForm.js
|
|_index.jsrather than
organisms
|_ userLogin
| |_Form.js
|_ machine
| |_Form.js
|
|_index.js