Typescript 中的forwardRef 和defaultProps

2024-05-04

我正在尝试在forwardRef 中使用defaultProps。 当我使用没有forwardRef的MessageBox时,它与defaultProps配合得很好。 但是,当我使用forwardRef 时,会发生错误。怎么解决呢?

打字稿:3.4.5“反应”:“^16.8.6”,

import React, { forwardRef } from "react";

export interface MessageBoxProps {
  test: string;
  children: any;
}

const defaultProps: Partial<MessageBoxProps> = {
  test: "test"
};

const MessageBox = forwardRef<HTMLDivElement, MessageBoxProps>((props, ref) => {
  return <p>{props.test}</p>;
});

MessageBox.defaultProps = defaultProps;

export default MessageBox;

export default function App() {
  const ref = React.useRef<HTMLDivElement>(null);
  return (
    <div className="App">
      <Test ref={ref} />
    </div>
  );
}
Type '{ ref: RefObject<HTMLDivElement>; }' is missing the following properties from type 'MessageBoxProps': test, children

https://codesandbox.io/s/forwardref-with-typescript-knhu3?file=/src/App.tsx:83-244 https://codesandbox.io/s/forwardref-with-typescript-knhu3?file=/src/App.tsx:83-244


简短的答案似乎是:您不能将 defaultProps 与前向引用一起使用。 您应该使用 ES2015 默认初始值设定项,如下所述here https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#explicit-types-on-defaultprops

这是我在 @types/react 源中的发现,也许其他人可以帮助进一步理解这一点。

  1. 在将组件提供给 React.forwardRef 之前,您无法在组件上定义默认属性,这绝对是故意的forwardRef 参数类型一 github : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ef99180a81bea833ccb9e80631636fa4a959f17c/types/react/index.d.ts#L546-L559

     interface ForwardRefRenderFunction<T, P = {}> {
         (props: P, ref: ForwardedRef<T>): ReactElement | null;
         displayName?: string | undefined;
         // explicit rejected with `never` required due to
         // https://github.com/microsoft/TypeScript/issues/36826
         /**
          * defaultProps are not supported on render functions
          */
         defaultProps?: never | undefined;
         /**
          * propTypes are not supported on render functions
          */
         propTypes?: never | undefined;
     }
    
  2. React.forwardRef 的返回类型有一个默认的 prop 字段,表明它在 jsx 中使用时应该正确输入github上的forwardRef类型和返回类型: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ef99180a81bea833ccb9e80631636fa4a959f17c/types/react/index.d.ts#L776-L781

     interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> {
         defaultProps?: Partial<P> | undefined;
         propTypes?: WeakValidationMap<P> | undefined;
     }
    
     function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
    
  3. Typescript 文档明确指出,他们在库端添加了对 prop 类型转换的支持,以便允许 React defaultProp 正确键入来自 typescript 3 的新功能:“支持 JSX 中的 defaultProps” https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#support-for-defaultprops-in-jsx:

TypeScript 3.0 在 JSX 命名空间中添加了对新类型别名的支持,称为库管理属性。该辅助类型定义了组件 Props 类型的转换,然后用于检查针对它的 JSX 表达式;因此允许自定义,例如:如何处理提供的 props 和推断的 props 之间的冲突、如何映射推论、如何处理可选性以及如何组合来自不同位置的推论。

However该页面还提到了以下功能组件:

对于功能组件(以前称为 SFC),请使用 ES2015 默认初始值设定项:

function Greet({ name = "world" }: Props) {
  return <div>Hello {name.toUpperCase()}!</div>;
}

但我们还不止于此。如果我们真的想使用defaultProp怎么办?我需要知道为什么它不起作用。

  1. 在 @types/react 中搜索 LibraryManagedAttributes 仅给出一次命中:来自github的代码: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ef99180a81bea833ccb9e80631636fa4a959f17c/types/react/index.d.ts#L3135-L3139

     type LibraryManagedAttributes<C, P> = C extends React.MemoExoticComponent<infer T> | React.LazyExoticComponent<infer T>
         ? T extends React.MemoExoticComponent<infer U> | React.LazyExoticComponent<infer U>
             ? ReactManagedAttributes<U, P>
             : ReactManagedAttributes<T, P>
         : ReactManagedAttributes<C, P>;
    

是这个吗 ?我不会假装完全理解最后一段代码,但没有提到ForwardRefExotic组件那里。这是一个错误吗?如果在这个类型定义中添加一些东西,它可以工作吗?我应该打开一个问题吗?

让我知道你们的想法!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript 中的forwardRef 和defaultProps 的相关文章

  • Angular2 viewContainerRef.createComponent 工作正常

    我使用 viewContainerRef createComponent 将动态组件加载到根组件 但实际上它附加了错误的位置 my code app compoment ts export class AppComponent privat
  • 从 Angular 11 更新到 12 时,MatSelect OverlayDir 现在是私有的。现在如何访问它?

    在 Angular 11 中 node modules angular material select 中有一个变量 Overlay pane containing the options deprecated To be turned i
  • 联合数据类型上的条件数据类型

    假设您有以下类型 type Foo prop1 foo prop2 null type Bar prop1 bar prop2 number type FooOrBar Foo Bar 是否可以使用条件类型重写上述代码 我已经尝试过以下方法
  • 如何包装内在组件,保留大部分 Props?

    我想用我自己的 React 功能组件包装一个标准按钮 但我希望新组件的用户能够设置 几乎所有底层按钮的道具 当然 我想保持正确的打字 所以如果 WrappedButton 包含一个button then
  • 下一张图片不采用类属性

    我正在使用 Next js 和next image显示图像 但 CSS 在其中不起作用 该图像是 SVG 格式 我已将其放在公共文件夹中 我正在使用 Tailwind CSS 与此一起使用
  • 为现有模块创建 d.ts 文件

    我正在尝试创建一个d ts文件为React 静态容器 https github com reactjs react static container图书馆 NPM 中安装的库如下所示 var React require react var
  • 使用 React 渲染来自 Express 的 Flash 消息

    我已经搜索了很多 但一直无法找到一种简单的方法来从 Express 获取 Flash 消息并在 React 中渲染它们 我需要访问 Express 服务器上的数据 但是存储这些数据并将其传递给 React 的最佳方式是什么 我正在考虑传递一
  • 无法绑定,因为它不是选择器组件的已知属性

    我想将变量从一个组件传递到另一个组件 并且我正在使用 input 这是我的父组件 Component selector aze templateUrl aze component html styleUrls aze component s
  • Redux 减速器的副作用

    Redux 减速器应该没有副作用 但是 如果某个操作应该触发浏览器中文件的下载 其中内容基于商店的状态 该怎么办 这当然应该算作副作用吗 像下面这样的方法可以吗 还是我应该寻找替代方法 case SAVE GRID const json s
  • Angular 2 获取当前路线

    所以我需要以某种方式检查我是否在主页上执行某些操作 而在其他页面上则不执行此操作 该组件也在所有页面上导入 如果我在主页上 如何检测该组件 Thanks 尝试这个 import Router from angular router expo
  • 如何在 Angular 项目中使用 Bootstrap?

    我开始我的第一次Angular应用程序和我的基本设置已完成 我怎样才能添加引导程序我的申请 如果您可以提供一个示例 那么这将是一个很大的帮助 如果您使用Angular CLI要生成新项目 还有另一种方法可以使 bootstrap 可访问角度
  • 从输入类型编号获取无效值

    我正在使用输入类型数字 当它无效时 我如何从中获取值 例如 使用类型编号并仅打印 e 这本身是无效的 我正在使用 React 但我认为这个问题非常普遍 onChange event console log event target valu
  • 如何将窗口注入到服务中?

    我正在用 TypeScript 编写一个 Angular 2 服务 它将利用localstorage 我想注入对浏览器的引用window对象到我的服务中 因为我不想引用任何全局变量 例如 Angular 1 x window 我怎么做 这目
  • 使用 rollup.js 创建 React 库时出现错误 null(读取“useState”)

    我正在使用 rollup js 创建一个反应库 但是当我运行时npm run build我收到一个错误 仿佛useState尝试从中检索钩子null Uncaught TypeError Cannot read properties of
  • Redux - 从函数调用操作

    我正在尝试从函数调用 redux 操作 我调用该函数的组件已连接到商店 但是 如果我通过以下操作 它就不起作用 function myFunc action action 有没有办法通过参数传递动作 谢谢 using bindActionC
  • 如何从嵌套的对象数组中获取每个父级的值

    所以我有多个对象数组 每个对象都包含一个子对象 e g const data id 1 name parent 1 children id c1 name child 1 children id g1 name grand 1 childr
  • 使用 Jest 和 React JS TestUtils 测试表单

    我有一个带有 3 个单选按钮的表单 如下所示 假名
  • 如何在 Vue SFC 中使用 Typescript 全局类型声明?

    In Vue2 Typescript我有的项目global d ts具有某些类型的文件 例如 全局 d ts type Nullable
  • webpack中动态加载外部模块失败

    我正在尝试建立以下架构 一个核心 React 应用程序 它具有一些基本功能 并且能够在运行时加载其他 React 组件 这些额外的 React 组件可以按需加载 并且它们在构建核心应用程序时不可用 因此它们不能包含在核心应用程序的捆绑包中
  • 在 TypeScript 中,可以在没有“new”关键字的情况下使用类吗?

    TypeScript 是包含类型的 ES6 Javascript 超集 可以使用以下方式声明一个类class关键字并使用实例化new关键字与 Java 中的关键字类似 我想知道 TypeScript 中是否有任何用例可以在不使用new关键词

随机推荐