Български

Разгледайте най-добрите практики за използване на TypeScript с React за изграждане на стабилни, мащабируеми и лесни за поддръжка уеб приложения. Научете за структура на проекта, дизайн на компоненти, тестване и оптимизация.

TypeScript с React: Най-добри практики за мащабируеми и поддържаеми приложения

TypeScript и React са мощна комбинация за изграждане на модерни уеб приложения. TypeScript въвежда статично типизиране в JavaScript, подобрявайки качеството и поддръжката на кода, докато React предоставя декларативен и компонентно-базиран подход за изграждане на потребителски интерфейси. Тази блог публикация разглежда най-добрите практики за използване на TypeScript с React за създаване на стабилни, мащабируеми и лесни за поддръжка приложения, подходящи за глобална аудитория.

Защо да използваме TypeScript с React?

Преди да се потопим в най-добрите практики, нека разберем защо TypeScript е ценно допълнение към разработката с React:

Създаване на TypeScript React проект

Използване на Create React App

Най-лесният начин да стартирате нов TypeScript React проект е като използвате Create React App с шаблона за TypeScript:

npx create-react-app my-typescript-react-app --template typescript

Тази команда създава базов React проект с конфигуриран TypeScript, включително необходимите зависимости и файл tsconfig.json.

Конфигуриране на tsconfig.json

Файлът tsconfig.json е сърцето на вашата TypeScript конфигурация. Ето някои препоръчителни настройки:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": [
    "src"
  ]
}

Ключови опции, които да вземете предвид:

Най-добри практики за React компоненти с TypeScript

Типизиране на пропъртита (props) на компоненти

Един от най-важните аспекти при използването на TypeScript с React е правилното типизиране на пропъртитата (props) на вашите компоненти. Използвайте интерфейси или псевдоними на типове (type aliases), за да дефинирате формата на обекта с пропъртита.

interface MyComponentProps {
  name: string;
  age?: number; // Незадължително пропърти
  onClick: () => void;
}

const MyComponent: React.FC = ({ name, age, onClick }) => {
  return (
    

Hello, {name}!

{age &&

You are {age} years old.

}
); };

Използването на React.FC<MyComponentProps> гарантира, че компонентът е функционален и че пропъртитата са правилно типизирани.

Типизиране на състоянието (state) на компонента

Ако използвате класови компоненти, ще трябва да типизирате и състоянието (state) на компонента. Дефинирайте интерфейс или псевдоним на тип за обекта на състоянието и го използвайте в дефиницията на компонента.

interface MyComponentState {
  count: number;
}

class MyComponent extends React.Component<{}, MyComponentState> {
  state: MyComponentState = {
    count: 0
  };

  handleClick = () => {
    this.setState({
      count: this.state.count + 1
    });
  };

  render() {
    return (
      

Count: {this.state.count}

); } }

За функционални компоненти, използващи куката useState, TypeScript често може да изведе типа на променливата на състоянието, но можете и изрично да го зададете:

import React, { useState } from 'react';

const MyComponent: React.FC = () => {
  const [count, setCount] = useState(0);

  return (
    

Count: {count}

); };

Използване на предпазители на типове (Type Guards)

Предпазителите на типове са функции, които стесняват типа на променлива в определен обхват. Те са полезни при работа с обединени типове (union types) или когато трябва да се уверите, че дадена променлива е от конкретен тип, преди да извършите операция.

interface Circle {
  kind: "circle";
  radius: number;
}

interface Square {
  kind: "square";
  side: number;
}

type Shape = Circle | Square;

function isCircle(shape: Shape): shape is Circle {
  return shape.kind === "circle";
}

function getArea(shape: Shape): number {
  if (isCircle(shape)) {
    return Math.PI * shape.radius ** 2;
  } else {
    return shape.side ** 2;
  }
}

Функцията isCircle е предпазител на тип, който проверява дали Shape е Circle. В рамките на блока if TypeScript знае, че shape е Circle и ви позволява достъп до неговото свойство radius.

Обработка на събития

При обработка на събития в React с TypeScript е важно правилно да се типизира обектът на събитието. Използвайте подходящия тип събитие от именното пространство React.

const MyComponent: React.FC = () => {
  const handleChange = (event: React.ChangeEvent) => {
    console.log(event.target.value);
  };

  return (
    
  );
};

В този пример React.ChangeEvent<HTMLInputElement> се използва за типизиране на обекта на събитието за промяна (change event) на input елемент. Това осигурява достъп до свойството target, което е HTMLInputElement.

Структура на проекта

Добре структурираният проект е от решаващо значение за поддръжката и мащабируемостта. Ето една препоръчителна структура на проекта за TypeScript React приложение:

src/
├── components/
│   ├── MyComponent/
│   │   ├── MyComponent.tsx
│   │   ├── MyComponent.module.css
│   │   └── index.ts
├── pages/
│   ├── HomePage.tsx
│   └── AboutPage.tsx
├── services/
│   ├── api.ts
│   └── auth.ts
├── types/
│   ├── index.ts
│   └── models.ts
├── utils/
│   ├── helpers.ts
│   └── constants.ts
├── App.tsx
├── index.tsx
├── react-app-env.d.ts
└── tsconfig.json

Ключови моменти:

Използване на куки (Hooks) с TypeScript

Куките на React ви позволяват да използвате състояние и други функции на React във функционални компоненти. TypeScript работи безпроблемно с куките, осигурявайки типова безопасност и подобрено изживяване за разработчика.

useState

Както беше показано по-рано, можете изрично да типизирате променливата на състоянието, когато използвате useState:

import React, { useState } from 'react';

const MyComponent: React.FC = () => {
  const [count, setCount] = useState(0);

  return (
    

Count: {count}

); };

useEffect

Когато използвате useEffect, обръщайте внимание на масива със зависимости. TypeScript може да ви помогне да уловите грешки, ако забравите да включите зависимост, която се използва в ефекта.

import React, { useState, useEffect } from 'react';

const MyComponent: React.FC = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]); // Добавете 'count' към масива със зависимости

  return (
    

Count: {count}

); };

Ако пропуснете count от масива със зависимости, ефектът ще се изпълни само веднъж, когато компонентът се монтира, и заглавието на документа няма да се актуализира при промяна на брояча. TypeScript ще ви предупреди за този потенциален проблем.

useContext

Когато използвате useContext, трябва да предоставите тип за стойността на контекста.

import React, { createContext, useContext } from 'react';

interface ThemeContextType {
  theme: string;
  toggleTheme: () => void;
}

const ThemeContext = createContext(undefined);

const ThemeProvider: React.FC = ({ children }) => {
  // Имплементирайте логиката за темата тук
  return (
     {} }}>
      {children}
    
  );
};

const MyComponent: React.FC = () => {
  const { theme, toggleTheme } = useContext(ThemeContext) as ThemeContextType;

  return (
    

Theme: {theme}

); }; export { ThemeProvider, MyComponent };

Като предоставяте тип за стойността на контекста, вие гарантирате, че куката useContext връща стойност с правилния тип.

Тестване на TypeScript React компоненти

Тестването е съществена част от изграждането на стабилни приложения. TypeScript подобрява тестването, като осигурява типова безопасност и подобрено покритие на кода.

Модулно тестване (Unit Testing)

Използвайте рамки за тестване като Jest и React Testing Library, за да тествате модулно вашите компоненти.

// MyComponent.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('renders the component with the correct name', () => {
    render();
    expect(screen.getByText('Hello, John!')).toBeInTheDocument();
  });

  it('calls the onClick handler when the button is clicked', () => {
    const onClick = jest.fn();
    render();
    fireEvent.click(screen.getByRole('button'));
    expect(onClick).toHaveBeenCalledTimes(1);
  });
});

Проверката на типовете в TypeScript помага за улавяне на грешки във вашите тестове, като например подаване на неправилни пропъртита или използване на грешни обработчики на събития.

Интеграционно тестване

Интеграционните тестове проверяват дали различните части на вашето приложение работят правилно заедно. Използвайте инструменти като Cypress или Playwright за тестване от край до край.

Оптимизация на производителността

TypeScript може също да помогне с оптимизацията на производителността, като улавя потенциални „тесни места“ в производителността в ранен етап от процеса на разработка.

Мемоизация

Използвайте React.memo, за да мемоизирате функционални компоненти и да предотвратите ненужни прерисувания.

import React from 'react';

interface MyComponentProps {
  name: string;
}

const MyComponent: React.FC = ({ name }) => {
  console.log('Rendering MyComponent');
  return (
    

Hello, {name}!

); }; export default React.memo(MyComponent);

React.memo ще прерисува компонента само ако пропъртитата са се променили. Това може значително да подобри производителността, особено при сложни компоненти.

Разделяне на кода (Code Splitting)

Използвайте динамични импорти, за да разделите кода си на по-малки части и да ги зареждате при поискване. Това може да намали първоначалното време за зареждане на вашето приложение.

import React, { Suspense } from 'react';

const MyComponent = React.lazy(() => import('./MyComponent'));

const App: React.FC = () => {
  return (
    Loading...
}> ); };

React.lazy ви позволява динамично да импортирате компоненти, които се зареждат само когато са необходими. Компонентът Suspense предоставя резервен потребителски интерфейс, докато компонентът се зарежда.

Заключение

Използването на TypeScript с React може значително да подобри качеството, поддръжката и мащабируемостта на вашите уеб приложения. Следвайки тези най-добри практики, можете да използвате силата на TypeScript, за да изградите стабилни и производителни приложения, които отговарят на нуждите на глобалната аудитория. Не забравяйте да се съсредоточите върху ясни дефиниции на типове, добре структурирана организация на проекта и задълбочено тестване, за да осигурите дългосрочния успех на вашите проекти.

Допълнителни ресурси