# Найкращі практики кодової бази ## Загальний JavaScript In most cases, our [linter](how-to-setup-freecodecamp-locally.md#follow-these-steps-to-get-your-development-environment-ready) will warn of any formatting which goes against this codebase's preferred practice. Рекомендується використовувати функціональні компоненти замість класових компонентів. ## Specific TypeScript ### Migrating a JavaScript File to TypeScript #### Збереження історії файлів Git 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. Найкращі умови для досягнення цього: 1. Перейменувати файл 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] Такі редактори, як VSCode, все одно показуватимуть, що файл видалено та створено новий. Якщо ви використовуєте `git add .`, тоді VSCode покаже файл як перейменований в процесі ### Naming Conventions #### Інтерфейси та типи For the most part, it is encouraged to use interface declarations over type declarations. React Component Props - суфікс `Props` ```typescript interface MyComponentProps {} // type MyComponentProps = {}; const MyComponent = (props: MyComponentProps) => {}; ``` React Stateful Components - суфікс `State` ```typescript interface MyComponentState {} // type MyComponentState = {}; class MyComponent extends Component {} ``` За замовчуванням - ім'я об'єкта в PascalCase ```typescript interface MyObject {} // type MyObject = {}; const myObject: MyObject = {}; ``` ## Redux ### Визначення дій ```typescript enum AppActionTypes = { actionFunction = 'actionFunction' } export const actionFunction = ( arg: Arg ): ReducerPayload => ({ type: AppActionTypes.actionFunction, payload: arg }); ``` ### Як підключити 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 Усередині компонента імпортуйте необхідні дії та селектори. ```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); ``` ## Додаткова література - [Документація по TypeScript](https://www.typescriptlang.org/docs/) - [Підказки по TypeScript з React](https://github.com/typescript-cheatsheets/react#readme)