This is based on the article: A few notes on naming and project structure: 2024SP_COMP_SCI_394-0_SEC2 Agile Software Development (northwestern.edu).
and
Folder Structure
- Flat Structure
Simpler, but less organized if we have lots of component-specific files like css, test files
src βββ components βββ Toolbar.tsx βββ Toobar.test.tsx // jest test file βββ Toobar.scss/css // stylesheet file βββ MenuItem.tsx βββ Avatar.tsx βββ UserEditForm.tsx βββ containers βββ HomeScreen.tsx βββ Dashboard.tsx βββ UserProfile.tsx
- Deeper Structure with one component as a folder, which can contain both the index.tsx or jsx file and its related css/scss file. Within theΒ
components
Β folder, PascalCase components to represent something like this:
More organized especially if we have multiple component-specific files but more complex
src βββ components βββ Toolbar βββ index.tsx βββ MenuItem βββ index.tsx βββ Input βββ __tests__ | βββ Input.test.tsx // jest unit tests for "index.tsx" βββ index.tsx // all required code/styles to be exported βββ styles.scss // styles required by "index.tsx" βββ containers βββ Dashboard βββ index.tsx βββ UserProfile βββ index.tsx
Group Folders
- By the level/granularity of the functions
src βββ components βββ Toolbar.tsx βββ Toobar.test.tsx // jest test file βββ Toobar.scss/css // stylesheet file βββ MenuItem.tsx βββ Avatar.tsx βββ UserEditForm.tsx βββ containers βββ HomeScreen.tsx βββ Dashboard.tsx βββ UserProfile.tsx
- By the app structures
src βββ appframe βββ Toolbar.tsx βββ Toobar.test.tsx // jest test file βββ Toobar.scss/css // stylesheet file βββ MenuItem.tsx βββ HomeScreen.tsx βββ dashboard βββ Chart.tsx βββ ControlForm.tsx βββ DashboardFrame.tsx
Extensions
- VSCode TypeScript Linter
- VSCode Copilot
Naming
- Main folder: smallcases
- File Names:
- For non-component files,Β camelCaseΒ orΒ kebab-caseΒ is common.
- Component Names: PascalCase
- snake-case or camelCase for css (stylesheets)
β camelCase for CSS modules
why? bundlers (like Webpack) don't support snake-case imports
// snake-case import "./styles.css"; <input className="snake-case" type="text" value="" onChange={this.handleChange} /> // camel-case import { camelCaseClassName } from "./styles.css"; <input className={camelCaseClassName} type="text" value="" onChange={this.handleChange} />
- TypeScript Types and Interfaces: Prefix interfaces with an I, like IProps or IState, to distinguish them from classes and other types3Links to an external site.
- Event Handlers: Start the names with handle, such as handleClick or handleInputChange.
- State Variables: Use descriptive names that reflect their purpose, like isLoading or userList.
- Props: Be descriptive and clear. For example, instead of data, use userData or profileData.
- Hooks: For custom hooks, use the use prefix, like useAuth or useFormInput.
- Avoid default exporting an anonymous function:
// don't do this. It will show a bunch of vague <_default /> in enzyme tests export default () => ( <p>Anonymous Function</p> );
CI/CD
- run
npm run lint
every time before you commit (or as a pre-commit github action)
- run tests?
Β
Β