diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 6f9b0422d1..323a1fe8bc 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -3,6 +3,7 @@ - [Frequently Asked Questions](FAQ.md) - **Code Contribution** - [Set up freeCodeCamp locally](how-to-setup-freecodecamp-locally.md) + - [Codebase best practices](codebase-best-practices.md) - [Open a pull request](how-to-open-a-pull-request.md) - [Work on coding challenges](how-to-work-on-coding-challenges.md) - [Work on video challenges](how-to-help-with-video-challenges.md) diff --git a/docs/codebase-best-practices.md b/docs/codebase-best-practices.md new file mode 100644 index 0000000000..9fe6fc7720 --- /dev/null +++ b/docs/codebase-best-practices.md @@ -0,0 +1,135 @@ +# Codebase Best Practices + +## General JavaScript + +In most cases, our [linter](how-to-setup-freecodecamp-locally?id=follow-these-steps-to-get-your-development-environment-ready) will warn of any formatting which goes against this codebase's preferred practice. + +It is encouraged to use functional components over class-based components. + +## Specific TypeScript + +### Migrating a JavaScript File to TypeScript + +#### Retaining Git File History + +Sometimes changing the file from `.js` to `.ts` (or `.tsx`) causes the original file to be deleted, and a new one created, and other times the filename just changes - in terms of Git. Ideally, we want the file history to be preserved. + +The best bet at achieving this is to: + +1. Rename the file +2. Commit with the flag `--no-verify` to prevent Husky from complaining about the lint errors +3. Refactor to TypeScript for migration, in a separate commit + +> [!NOTE] +> Editors like VSCode are still likely to show you the file has been deleted and a new one created. If you use the CLI to `git add .`, then VSCode will show the file as renamed in stage + +### Naming Conventions + +#### Interfaces and Types + +For the most part, it is encouraged to use interface declarations over type declarations. + +React Component Props - suffix with `Props` + +```typescript +interface MyComponentProps {} +// type MyComponentProps = {}; +const MyComponent = (props: MyComponentProps) => {}; +``` + +React Stateful Components - suffix with `State` + +```typescript +interface MyComponentState {} +// type MyComponentState = {}; +class MyComponent extends Component {} +``` + +Default - object name in PascalCase + +```typescript +interface MyObject {} +// type MyObject = {}; +const myObject: MyObject = {}; +``` + + + + + +## Redux + +### Action Definitions + +```typescript +enum AppActionTypes = { + actionFunction = 'actionFunction' +} + +export const actionFunction = ( + arg: Arg +): ReducerPayload => ({ + type: AppActionTypes.actionFunction, + payload: arg +}); +``` + +### How to Reduce + +```typescript +// Base reducer action without payload +type ReducerBase = { type: T }; +// Logic for handling optional payloads +type ReducerPayload = + T extends AppActionTypes.actionFunction + ? ReducerBase & { + payload: AppState['property']; + } + : ReducerBase; + +// Switch reducer exported to Redux combineReducers +export const reducer = ( + state: AppState = initialState, + action: ReducerPayload +): AppState => { + switch (action.type) { + case AppActionTypes.actionFunction: + return { ...state, property: action.payload }; + default: + return state; + } +}; +``` + +### How to Dispatch + +Within a component, import the actions and selectors needed. + +```tsx +// Add type definition +interface MyComponentProps { + actionFunction: typeof actionFunction; +} +// Connect to Redux store +const mapDispatchToProps = { + actionFunction +}; +// Example React Component connected to store +const MyComponent = ({ actionFunction }: MyComponentProps): JSX.Element => { + const handleClick = () => { + // Dispatch function + actionFunction(); + }; + return ; +}; + +export default connect(null, mapDispatchToProps)(MyComponent); +``` + + + + +## Further Literature + +- [TypeScript Docs](https://www.typescriptlang.org/docs/) +- [TypeScript with React CheatSheet](https://github.com/typescript-cheatsheets/react#readme) diff --git a/docs/how-to-setup-freecodecamp-locally.md b/docs/how-to-setup-freecodecamp-locally.md index 41e60577a5..b5e151b8bd 100644 --- a/docs/how-to-setup-freecodecamp-locally.md +++ b/docs/how-to-setup-freecodecamp-locally.md @@ -19,7 +19,7 @@ We also support Windows 10 via WSL2, which you can prepare by [reading this guid Some community members also develop on Windows 10 natively with Git for Windows (Git Bash), and other tools installed on Windows. We do not have official support for such a setup at this time, we recommend using WSL2 instead. -**Prerequisites:** +#### Prerequisites: | Prerequisite | Version | Notes | | --------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------- | @@ -42,7 +42,7 @@ npm -v Once you have the prerequisites installed, you need to prepare your development environment. This is common for many development workflows, and you will only need to do this once. -**Follow these steps to get your development environment ready:** +##### Follow these steps to get your development environment ready: 1. Install [Git](https://git-scm.com/) or your favorite Git client, if you haven't already. Update to the latest version; the version that came bundled with your OS may be outdated. diff --git a/docs/index.html b/docs/index.html index 2917ef7c96..8dd686409b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,96 +1,108 @@ + + + Contribution Guidelines | freeCodeCamp.org + + + + + + + + - - - Contribution Guidelines | freeCodeCamp.org - - - - - - - - + + + + - - - - + - + + + + + + - - - - - + + + - + +
+ + return markdown + '\n----\n' + dynamicText; + // -- do not add logic below this line -- + }); + } + ] + }; + - + - - + + - - - - - - + + + + + + + + + - - - - - + + + +