Как добавить типы TypeScript в useReducer

useReducer — это отличный способ абстрагироваться от некоторых сложностей вашего приложения в React.
В этом посте я покажу вам, как можно добавить типы TypeScript в редукторы и сэкономить часы на отладке! 🥳

По мере роста вашего приложения вы начинаете переходить от useState к useReducer, что позволит скрыть часть сложности вашего приложения. Однако без правильных типов вы можете неправильно использовать функцию dispatch функции useReducer и столкнуться с непредвиденными ошибками.

Представьте себе форму входа в систему, состоянием которой управляет этот редуктор:

function authReducer(state, action) {
  switch (action.type) {
    case "success":
      return { success: true, username: action.value, error: "" }
    case "failure":
      return { success: false, username: "", error: action.value }
    default:
      throw Error()
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Вы можете использовать этот редуктор в своем приложении React следующим образом:

const [state, dispatch] = useReducer(authReducer)

function submit(data) {
  try {
    const response = await axios.post("/api/login", { data });
    dispatch({
      type: "success",
      value: response.data.user,
    });
  } catch (error) {
    dispatch({
      type: "failure",
      value: error.message,
    });
  } 
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Это работает, однако, без использования типов ничто не помешает вам случайно это сделать:

dispatch({
  type: "failure",
  value: response.data.user,
})
Войти в полноэкранный режим Выйти из полноэкранного режима

Вот почему я люблю вводить типы в свои редукторы как можно раньше, чтобы такие ошибки отлавливались во время компиляции. Давайте сделаем это на нашем примере:

type User = {
  id: string;
  username: string;
}

export type AuthState = {
  success: boolean;
  user: User | null;
  error: string;
}

export type AuthAction = {
  type: "success" | "failure";
  value: User | string;
}

export function authReducer(state: AuthState, action: AuthAction) {
  switch (action.type) {
    case "success":
      return { success: true, user: action.value, error: "" }
    case "failure":
      return { success: false, user: null, error: action.value }
    default: throw Error()
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

в то время как мы набрали наш редуктор сейчас, из-за того, как мы набрали действие:

type AuthAction = {
  type: "success" | "failure";
  value: User | string;
}
Enter fullscreen mode Выйти из полноэкранного режима

все еще возможно отправить неправильное значение неправильному типу действия, т.е. сообщение об ошибке для типа «success»:

dispatch({
  type: "success",
  value: "Something went wrong",
})
Войти в полноэкранный режим Выход из полноэкранного режима

Поэтому давайте уточним, какое именно значение принимает тип:

type AuthAction =
  | {
    type: "success";
    value: User;
  }
  | {
    type: "failure";
    value: string;
  }
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь давайте напечатаем использование reducer в нашем приложении React:

import { Reducer } from "react";
import { authReducer, authState, AuthState, AuthAction } from './auth_reducer';

const [state, dispatch] = useReducer<
  Reducer<AuthState, AuthAction>
>(authReducer, authState)

function submit(data) {
  try {
    const response = await axios.post("/api/login", { data });
    dispatch({
      type: "success",
      value: response.data.user,
    });
  } catch (error) {
    dispatch({
      type: "failure",
      value: error.message,
    });
  } 
}
Enter fullscreen mode Выйти из полноэкранного режима

Теперь если вы попытаетесь вызвать тип «success» с неправильным значением:

dispatch({
  type: "success",
  value: "Something went wrong",
})
Enter fullscreen mode Выйти из полноэкранного режима

Вы получите следующую ошибку от TypeScript:

Type 'string' has no properties in common with type 'User'.
Enter fullscreen mode Выйти из полноэкранного режима

Поздравляем, вы только что добавили типы TypeScript в свой редуктор, сделав его более устойчивым и простым в использовании! 🙌

Оцените статью
devanswers.ru
Добавить комментарий