【问题标题】:How to properly type a React ErrorBoundary class component in Typescript?如何在 Typescript 中正确键入 React ErrorBoundary 类组件?
【发布时间】:2021-01-03 02:23:18
【问题描述】:

这是我目前关于如何在 Typescript 中正确键入 React ErrorBoundary 类组件的尝试:

import React from "react";
import ErrorPage from "./ErrorPage";
import type { Store } from "redux";   // I'M PASSING THE REDUX STORE AS A CUSTOM PROP

interface Props {
  store: Store         // THIS IS A CUSTOM PROP THAT I'M PASSING
}

interface State {      // IS THIS THE CORRECT TYPE FOR THE state ?
  hasError: boolean
}

class ErrorBoundary extends React.Component<Props,State> {
  
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error): State {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo: React.ErrorInfo): void {
    // You can also log the error to an error reporting service
    // logErrorToMyService(error, errorInfo);
    console.log("error: " + error);
    console.log("errorInfo: " + JSON.stringify(errorInfo));
    console.log("componentStack: " + errorInfo.componentStack);
  }

  render(): React.ReactNode {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return(
        <ErrorPage
          message={"Something went wrong..."}
        />
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

这个问题是关于这个ErrorBoundary 类组件的类型。我将它分成几部分以使其更容易。


A 部分:道具和状态的类型

我做的对吗?

interface Props {
  store: Store         // THIS IS A CUSTOM PROP THAT I'M PASSING
}

interface State {      // IS THIS THE CORRECT TYPE FOR THE state ?
  hasError: boolean
}

class ErrorBoundary extends React.Component<Props,State> {}

B 部分:getDerivedStateFromError(error)

error 参数应该选择什么类型?返回类型应该是State 类型吧?

static getDerivedStateFromError(error): State {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

C部分:componentDidCatch(error, errorInfo: React.React.ErrorInfo)

error 参数应该选择什么类型?对于errorInfo,React 确实有一个似乎是正确的ErrorInfo 类型。是吗?返回类型应该是void,对吗?

componentDidCatch(error, errorInfo: React.ErrorInfo): void {
    console.log("error: " + error);
    console.log("errorInfo: " + JSON.stringify(errorInfo));
    console.log("componentStack: " + errorInfo.componentStack);
}

D 部分:render() 方法

返回类型应该是ReactNode 吗?

render(): React.ReactNode {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return(
        <ErrorPage
          message={"Something went wrong..."}
        />
      );
    }

    return this.props.children;
  }

【问题讨论】:

  • 是这个语法吗:import type { Store } from "redux";允许吗?
  • @captain-yossarian 是的,它似乎工作得很好。但是import type 语法是在较新版本的 Typescript 中发布的,不确定是哪一个,但它在某些旧版本中不起作用。
  • 你应该将 redux store 传递给 而不是直接传递给你的组件
  • 我也在这样做。但不适用于ErrorBoundary。但我想我可以从react-redux 使用useStore() 访问商店,因为ErrorBoundary 将在&lt;Provider store={store}&gt; 内。谢谢。 编辑: 实际上我不能在类组件中使用useStore。才发现的。收到错误消息:React Hook “useStore”不能在类组件中调用。必须在 React 函数组件或自定义 React Hook 函数中调用 React Hooks。
  • C 部分:此成员必须具有“覆盖”修饰符,因为它覆盖了基类“组件,错误边界状态,任何>”中的成员。ts(4114)部分D:该成员必须具有“覆盖”修饰符,因为它覆盖了基类“Component, ErrorBoundaryState, any>”.ts(4114) 中的成员

标签: reactjs typescript typescript-typings react-class-based-component react-error-boundary


【解决方案1】:

您将在来自@types/react 的文件index.d.ts 中获得所有答案。如果您使用的是 VSCode 之类的 IDE,您可以 Ctrl+单击一个类型直接转到其定义。

这是您问题的准确答案,但在此之前,我建议您更喜欢使用 react hooks 而不是类。


由 OP 编辑​​:我从不使用类组件,总是更喜欢函数和钩子,但来自 React docs on Error Boundaries:

错误边界的工作方式类似于 JavaScript catch {} 块,但用于组件。 只有类组件可以是错误边界。


我给出的行是来自 index.d.ts 在版本 16.9.49 中的行。

A 部分:是的,就是这样。

B 部分:正如您在第 658 行看到的,error 的类型为 any,返回类型是 statenull 的一部分。

C 部分:在第 641 行,您将看到错误类型为 Error,返回类型为 void

D 部分:在第 494 行,您可以看到渲染应该返回 ReactNode...

【讨论】:

  • 谢谢,伙计。我现在只是在查看类型定义文件。我忘记了那些方法签名将在类型定义文件中。我决定将unknown 用于getDerivedStateFromError(error) 中的error 参数,而不是any
【解决方案2】:

您可以使用以下代码作为错误边界

import React, { Component, ErrorInfo, ReactNode } from "react";

interface Props {
  children: ReactNode;
}

interface State {
  hasError: boolean;
}

class ErrorBoundary extends Component<Props, State> {
  public state: State = {
    hasError: false
  };

  public static getDerivedStateFromError(_: Error): State {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error("Uncaught error:", error, errorInfo);
  }

  public render() {
    if (this.state.hasError) {
      return <h1>Sorry.. there was an error</h1>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

【讨论】:

    猜你喜欢
    • 2021-07-28
    • 2020-12-30
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2019-09-02
    相关资源
    最近更新 更多