Always use Typescript feature to prevent hidden bugs from Javascript.
If you are VSCode use, We suggest installing these following extensions and make the editor auto format after you saved
code --install-extension esbenp.prettier-vscode
code --install-extension dbaeumer.vscode-eslint
code --install-extension styled-components.vscode-styled-components
- Type shortcut ⌘ + shift + P
- Choose *Preferences: Open Settings (UI)
- Search by Editor: Format On Save
- Check the checkbox
Finally, please make sure the VSCode configuration file (JSON) have configurations as below:
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
Please follow the configuration below for consistency and control
Constant variables: camelCase
For Boolean variables should start with is, has, and should
For Array should use the plural noun
const tmnId = 'tmn.1234566789'
let count = 0
const isModalVisible = false
const hasValue = true
const shouldUpdate = false
const users = ['Dang', 'Dum']
const userDetail = {
name: 'Tester',
occupations: [
'farmer',
'investor'
]
}
For function please use camelCase, start with Verb, and only use Arrow function
For handler function should start with on
const calculateNumber = (firstInput: number, secondInput: number) => firstInput + secondInput
const onClose = () => ({})
const onSubmitComplete = () => ({})
For Enumerate please use PascalCase
enum ActionType = {
Create = 1,
Update = 2
}
For Type and Interface use PascalCase start with I
type IOccupation = 'business' | 'farmer' | 'other'
interface IComponentProps {
title: string
onClick: () => void
onChange: (input: number) => void
}
For Component and Styled-Component please use PascalCase
const FundCard = ({ title, description }: IFundCard) => (
<Container>
...
</Container>
)
const Container = styled.div`
border: 1px solid red;
`
For Page please add a Page suffix to our page component.
const PurchasePage = () => {
return (...)
}
export default PurchasePage
The structure is based on Next.js framework.
/public
favicon.ico
/src
/components
/common
/button
/__tests__
Button.spec.tsx
Button.tsx
/auth
/__tests__
AuthForm.test.tsx
AuthForm.tsx
/[Name]
[Name].tsx
[Name].test.ts
/hooks
/types
/utils
/api
/__tests__
[HTTP_METHOD][Name]Api.spec.ts
[HTTP_METHOD][Name]Api.ts
/test
/api
authApi.spec.ts
/pages
index.test.tsx
/pages
/api
/auth
authApi.ts
_app.tsx
_document.tsx
index.tsx
Use only Functional components with Hooks
- Dependencies importing part
- Styled part
- Interface and Type part
- Component part
- Exporting part
// /src/components/counter/Counter.tsx
import { useState } from 'react'
import styled from 'styled-components'
const CounterLabel = styled.span`
font-size: 18px;
font-weight: bold;
`
const Container = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
`
const SubContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
`
interface ICounterProps {
title: string
}
const Counter = ({ title }: ICounterProps) => {
const [count, setCount] = useState(0)
return (
<Container>
<h3>{title}</h3>
<CounterLabel>{count}</CounterLabel>
<SubContainer>
<button onClick={() => setCount(count + 1)}>Increase</button>
<button onClick={() => setCount(count - 1)}>Decrease</button>
</SubContainer>
</Container>
)
}
export default Counter
If we want to export a single thing, use export default first. For many things use both export and export default.
export interface IExportingDetail {
title: string
index: number
}
const exportingDetail: IExportingDetail = {
title: 'Hello',
index: 0
}
export default exportingDetail
Please read the Redux style guide
If something needs to be changed or refactored later, add a // TODO:
comment to indicate what the issue is.
If you refactor code that has comments, please check afterward if the comments still make sense or need to be updated.
No !important postfix, for more information
No need to create new classname, please use styled-components instead. Except the tailwindcss
Paste every test file into __tests__
folder at the sibling layer of the code.
/src
/components
/button
/__tests__
Button.spec.tsx
Button.tsx
/apis
/__tests__
getUserStatus.spec.ts
getUserStatus.ts
The testing structure and lifecycle must align with Jest guideline.
Naming of test cases should start with should because Jest implements it function to make everyone read easier. We read a test case below as it clicking the purchase button normally.
describe('purchase page', () => {
beforeAll(() => {
...
})
afterEach(() => {
...
})
it('should clicking the purchase button normally', () => {
...
});
});
Always separate Logic From Configuration Write code that is reusable, scalable, and testable.
- Do not copy code to another place.
- Avoid using the same string twice in a project.
- Move shared logic to a shared place.
- Make sure you do not have to adapt changes in multiple places.