JavaRush /Курсы /Модуль 3: React /Типизация компонентов с использованием TypeScript — интер...

Типизация компонентов с использованием TypeScript — интерфейсы для компонентов и пропсов

Модуль 3: React
21 уровень , 5 лекция
Открыта

Типизация компонентов

В React Native (и React тоже) компоненты — это "стройматериалы" для создания интерфейсов. Важно убедиться, что они получают правильные "пропсы" (данные), чтобы работать корректно. Здесь на помощь и приходит TypeScript.

Начнём с простого примера.

Пример функционального компонента без типизации

import React from 'react';
import { Text, View } from 'react-native';

const Greeting = (props: any) => {
  return (
    <View>
      <Text>Hello, {props.name}!</Text>
    </View>
  );
};

export default Greeting;

В этом коде мы используем props: any, что означает, что мы вообще не ограничиваем тип передаваемых данных. Это плохо. Например, кто-то может случайно передать число вместо строки в качестве имени — и ваш компонент просто сломается.

Типизация пропсов с интерфейсами

Используем магию TypeScript и добавим интерфейс для пропсов:

import React from 'react';
import { Text, View } from 'react-native';

// Определяем интерфейс для пропсов
interface GreetingProps {
  name: string; // `name` должен быть строкой
}

const Greeting: React.FC<GreetingProps> = (props) => {
  return (
    <View>
      <Text>Hello, {props.name}!</Text>
    </View>
  );
};

export default Greeting;

Теперь всё стало лучше! Интерфейс GreetingProps описывает структуру и типы того, что ожидать в props. Если кто-то попробует передать число вместо строки — TypeScript немедленно скажет: "Остановись, это плохая идея!".

Деструктуризация пропсов

Код можно сделать ещё красивее, применив деструктуризацию:

import React from 'react';
import { Text, View } from 'react-native';

// Интерфейс для пропсов
interface GreetingProps {
  name: string;
}

const Greeting: React.FC<GreetingProps> = ({ name }) => {
  return (
    <View>
      <Text>Hello, {name}!</Text>
    </View>
  );
};

export default Greeting;

Вместо обращения к props.name мы теперь сразу извлекаем name из пропсов. Это не только удобно, но и улучшает читаемость.

Добавление необязательных пропсов

Не всегда все пропсы обязательны. Что если мы хотим добавить пропс age, который пользователь может (но не обязан) передать? Тогда мы можем отметить его как необязательный.

import React from 'react';
import { Text, View } from 'react-native';

// Интерфейс для пропсов
interface GreetingProps {
  name: string;
  age?: number; // необязательный пропс
}

const Greeting: React.FC<GreetingProps> = ({ name, age }) => {
  return (
    <View>
      <Text>Hello, {name}!</Text>
      {age && <Text>Your age is {age}.</Text>}
    </View>
  );
};

export default Greeting;

Символ ? после age указывает, что этот пропс необязателен. Теперь мы можем безопасно использовать age только в том случае, если он передан.

Использование значений по умолчанию

Иногда имеет смысл задать значения по умолчанию для пропсов. Это позволит компоненту корректно работать даже без передачи некоторых данных.

const Greeting: React.FC<GreetingProps> = ({ name, age = 18 }) => {
  return (
    <View>
      <Text>Hello, {name}!</Text>
      <Text>Your age is {age}.</Text>
    </View>
  );
};

Если age не указан, то он автоматически примет значение 18.

Пример: создаём карточку пользователя

Теперь давайте создадим немного более сложный компонент — карточку пользователя. Карточка будет отображать имя, возраст и статус активности пользователя.

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

// Интерфейс для пропсов
interface UserCardProps {
  name: string;
  age: number;
  isActive: boolean;
}

const UserCard: React.FC<UserCardProps> = ({ name, age, isActive }) => {
  return (
    <View style={[styles.card, isActive ? styles.active : styles.inactive]}>
      <Text style={styles.name}>{name}</Text>
      <Text>Age: {age}</Text>
      <Text>Status: {isActive ? 'Active' : 'Inactive'}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  card: {
    padding: 20,
    borderRadius: 10,
    margin: 10,
    backgroundColor: '#f0f0f0',
  },
  active: {
    backgroundColor: '#d4edda',
  },
  inactive: {
    backgroundColor: '#f8d7da',
  },
  name: {
    fontWeight: 'bold',
    fontSize: 18,
  },
});

export default UserCard;

Здесь мы описали типы для пропсов — name, age и isActive. А ещё добавили стилизацию, чтобы активные и неактивные карточки выглядели по-разному. Таким образом, мы создали компонент, который можно прямо использовать в реальном проекте.

Типизация состояния компонента

Давайте вспомним, что в React компоненты могут иметь собственное состояние. Мы используем useState для управления состоянием. В мире TypeScript мы можем типизировать это состояние.

import React, { useState } from 'react';
import { View, Button, Text } from 'react-native';

// Простой интерфейс для состояния
interface CounterState {
  count: number;
}

const Counter: React.FC = () => {
  const [state, setState] = useState<CounterState>({ count: 0 });

  const increment = () => setState({ count: state.count + 1 });

  return (
    <View>
      <Text>Count: {state.count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
};

export default Counter;

Здесь наше состояние представлено объектом с полем count. Мы явно указали его тип через <CounterState> в useState. Благодаря этому TypeScript помогает нам избежать ошибок при работе с состоянием.

Типизация сложных компонентов

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

interface Address {
  street: string;
  city: string;
  country: string;
}

interface ContactCardProps {
  name: string;
  email: string;
  address: Address; // Вложенный интерфейс
}

const ContactCard: React.FC<ContactCardProps> = ({ name, email, address }) => {
  return (
    <View>
      <Text>{name}</Text>
      <Text>{email}</Text>
      <Text>{address.street}, {address.city}, {address.country}</Text>
    </View>
  );
};

Интерфейс Address используется внутри ContactCardProps, что делает код более читаемым и компонент проще для поддержки.

2
Задача
Модуль 3: React, 21 уровень, 5 лекция
Недоступна
Создание компонента с несколькими пропсами и значением по умолчанию
Создание компонента с несколькими пропсами и значением по умолчанию
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ