Typescript 中的forwardRef 和defaultProps

Jil*_*dMe 6 typescript reactjs

我正在尝试在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;

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

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

小智 2

简短的答案似乎是:您不能将 defaultProps 与前向引用一起使用。\n您应该使用 ES2015 默认初始值设定项,如此处所述

\n

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

\n
    \n
  1. 在将组件提供给 React.forwardRef 之前,您无法在组件上定义默认 props,这绝对是有意为之的\nforwardRef参数类型一 github :

    \n
     interface ForwardRefRenderFunction<T, P = {}> {\n     (props: P, ref: ForwardedRef<T>): ReactElement | null;\n     displayName?: string | undefined;\n     // explicit rejected with `never` required due to\n     // https://github.com/microsoft/TypeScript/issues/36826\n     /**\n      * defaultProps are not supported on render functions\n      */\n     defaultProps?: never | undefined;\n     /**\n      * propTypes are not supported on render functions\n      */\n     propTypes?: never | undefined;\n }\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
  3. React.forwardRef 的返回类型有一个默认的 prop 字段,表明在 jsx\n github 上的forwardRef 类型和返回类型中使用时应该正确键入:

    \n
     interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> {\n     defaultProps?: Partial<P> | undefined;\n     propTypes?: WeakValidationMap<P> | undefined;\n }\n\n function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. Typescript 文档明确指出,他们在库端添加了对 prop 类型转换的支持,以便允许 React defaultProp 正确键入\n Typescript 3 新增内容:\'support for defaultProps in JSX\'

    \n
  6. \n
\n
\n

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

\n
\n

然而,该页面还提到了以下功能组件:

\n
\n

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

\n
function Greet({ name = "world" }: Props) {\n  return <div>Hello {name.toUpperCase()}!</div>;\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

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

\n
    \n
  1. 在 @types/react 中搜索 LibraryManagedAttributed 仅得到一次命中:\n来自 github 的代码:

    \n
     type LibraryManagedAttributes<C, P> = C extends React.MemoExoticComponent<infer T> | React.LazyExoticComponent<infer T>\n     ? T extends React.MemoExoticComponent<infer U> | React.LazyExoticComponent<infer U>\n         ? ReactManagedAttributes<U, P>\n         : ReactManagedAttributes<T, P>\n     : ReactManagedAttributes<C, P>;\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
\n

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

\n

让我知道你们的想法!

\n