Оглавление
1. Введение
2. Функциональные возможности и примеры
3. Заключение
Еще одна неделя, еще один пост. Продолжая свой предыдущий пост о Typescript для начинающих, я решил написать пост об использовании typescript в React-приложении для начинающих.
Введение
Поскольку популярность React в последние годы резко возросла, спрос на создание React-приложений с использованием Typescript также значительно увеличился.
Добавление Typescript в React
Обычно я использую шаблон create-react-app для запуска своего react-приложения. Чтобы добавить Typescript при создании нашего react-приложения, просто наберите эти дополнительные слова:
npx create-react-app my-app --template typescript
После завершения создания boilerplate откройте файл, и мы заметим, что некоторые файлы названы .ts
или .tsx
. Есть также новый файл, который называется tsconfig.ts
. В этом файле происходит все волшебство для Typescript. Typescript ищет файл tsconfig.json в корневой папке проекта, и этот файл предоставляет параметры конфигурации для компилятора.
Функциональные возможности и примеры
Прежде чем мы перейдем к рассмотрению примеров использования Typescript в React, давайте сделаем краткий обзор различных «типов» в Typescript.
- void: обозначает отсутствие какого-либо типа.
- Кортеж: работает как массив, но количество элементов здесь фиксировано. Типы элементов в кортеже известны и могут быть разных типов.
- enum: представляет собой группу постоянных значений, которые тесно связаны между собой и известны.
- any: позволяет присвоить переменной значение любого типа. Используется, когда тип значения неизвестен
- never: это тип, который не содержит значения, поэтому мы не можем присвоить переменной с типом never никакое значение.
- union: описывает значение, которое может быть одним из нескольких типов number | string | boolean.
- объект: Чтобы определить тип объекта, мы перечисляем его свойства и их типы: {x:число, y:число}.
В предыдущем посте есть более глубокое погружение в эти типы. Ознакомьтесь с ним, чтобы получить больше информации об этом.
Функциональные компоненты React
С выходом версии react 16.8 большинство пользователей перешли от использования компонентов классов к функциональным компонентам. Функциональный компонент React — это функция, которая получает объекты props и возвращает элементы JSX. В компонентах React нам необходимо учитывать тип поступающих реквизитов. Интеграция Typescript с функциональным компонентом довольно проста:
import {FC} from "react"
const Movies: FC<{title: string}> = ({ title }) => {
return (
<>
<h1>{message}</h1>
</>
);
};
Это один из способов определения функционального компонента с помощью Typescript. Мы присвоили функциональному компоненту тип FC
. FC — это псевдоним для функционального компонента. Также обратите внимание, что мы назначили типы для реквизитов, передаваемых в компонент, объявив их сразу после FC
.
Интерфейс
Другой способ присвоения типов реквизитам — это использование интерфейса. Интерфейсы Typescript необходимы для обеспечения определенной формы объекта. Интерфейс похож на объект, который содержит информацию о свойствах и типах объекта. Он явно сообщает компилятору Typescript об именах свойств и типах значений, которые может иметь объект. Кроме того, поскольку TypeScript способен выводить тип ваших переменных, вы можете убрать типизацию и из компонента FC. В итоге это будет выглядеть следующим образом:
import {FC} from "react"
// we can do it like this
const Movies: FC<{title: string, boxOffice: number}> = ({ title, boxOffice }) => {
return (
<>
<h1>{message}</h1>
</>
);
};
// or with an interface
interface MovieProps{
title: string;
boxOffice: number;
}
const Movies = ({ title, boxOffice }: MovieProps) => {
return (
<>
<h1>{message}</h1>
</>
);
};
// To keep the title prop optional. Just pass it this way
interface MovieProps{
title?: string;
boxOffice: number;
}
Использование интерфейсов имеет несколько преимуществ. Во-первых, код становится немного чище. Во-вторых, мы можем экспортировать интерфейс и использовать его в других частях нашего кода в качестве типа, сделав следующее: export interface MovieProps
, что обеспечивает последовательность в нашем коде. Мы также можем определить наши интерфейсы в одном файле и ссылаться на них из этого файла. Любые изменения также могут быть сделаны в одном месте.
Некоторые крючки React
useState
Для хуков useState
ожидаемый тип можно определить по начальному значению, переданному в useState
. Например:
const [title, setTitle] = useState("");
// is equal to
const [title, setTitle] = useState<string>("");
Поскольку в качестве начального значения передана пустая строка, typescript сделал вывод, что хранимое значение будет строкового типа. Однако, если мы хотим установить начальное значение как null
или undefined
, нам нужно передать union
типов следующим образом:
const [title, setTitle] = useState<string | null>(null);
И если мы ожидаем объект в хуке useState
, мы можем использовать interface
для определения типа объекта и присвоить его как тип в useState.
useRef
В большинстве случаев useRef используется для ссылки на элементы ввода в HTML. Например:
function movieSearch() {
const inputTitle = useRef(null);
return (
<>
<input ref={inputTitle} type="text" />
</>
);
}
В таких случаях мы можем использовать общий тип. Обратите внимание, что нам не нужно назначать null в качестве типа для общих типов, так как он уже принимает null
.
const inputTitle = useRef<HTMLInputElement>(null)
useEffect
Типизация хуков useEffect не требуется, поскольку они не имеют дело с возвращаемыми значениями. Функция очистки для хука useEffect также не считается значением, которое можно изменить, поэтому мы можем писать эти хуки как обычно.
События HTML
Наиболее распространенными событиями HTML являются события кнопок, события onChange и отправки формы. Ниже приведен пример того, как набирать эти события.
import { useState, ReactElement, ChangeEvent, FormEvent } from "react";
const App = (): ReactElement => {
const [title, setTitle] = useState<string | null>(null);
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
// handle event here...
};
return (
<form onSubmit={handleSubmit}>
<div>
<span>Email:</span>
<input
type="email"
name="email"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setTitle(e.currentTarget.value)
}
/>
</div>
<div>
<input type="Submit" value="Submit" />
</div>
</form>
);
};
Как видно из примера выше, событие отправки формы набирается как FormEvent
как импорт из модуля react node. Что касается события изменения, оно набирается как ChangeEvent<HTMLInputElement>
, поскольку свойство onChange находится в элементе ввода, который обрабатывает событие изменения. Что касается событий кнопки, оно показано как:
<button onClick={ (e: MouseEvent<HTMLButtonElement, MouseEvent>) => console.log("Clicked")}>button</button>
Обратите внимание, что в большинстве случаев типы событий кнопок и изменений могут быть вычислены с помощью Typescript, поэтому нет необходимости явно назначать типы для этих событий.
Заключение
Ну вот и все, это наиболее часто используемые типы при использовании React с Typescript. Этот список ни в коем случае не является исчерпывающим, и я понимаю, что не охватил некоторые важные части, такие как дженерики, определение типов для некоторых хуков (useContext или useMemo) или типизация различных типов компонентов React. Однако я еще не применял Typescript последовательно в этих темах и не понял основные концепции, стоящие за ними, чтобы писать об этом уверенно. Как только я это сделаю, я обновлю этот пост в блоге более подробной информацией. На данный момент я считаю, что информации в этом посте достаточно, чтобы начать использовать Typescript в React-приложении. Как всегда, больше информации можно найти в официальном документе: https://www.typescriptlang.org/docs/handbook/react.html.
До следующего раза. Берегите себя и будьте осторожны.