TypeScript React.FC<Props> 混淆

Posted

技术标签:

【中文标题】TypeScript React.FC<Props> 混淆【英文标题】:TypeScript React.FC<Props> confusion 【发布时间】:2020-05-16 05:23:30 【问题描述】:

我正在学习 TypeScript,有些地方让我感到困惑。下面是一点:

interface Props 
  name: string;


const PrintName: React.FC<Props> = (props) => 
  return (
    <div>
      <p style= fontWeight: props.priority ? "bold" : "normal" >
        props.name
      </p>
    </div>
  )


const PrintName2 = (props: Props) => 
  return (
    <div>
      <p style= fontWeight: props.priority ? "bold" : "normal" >
        props.name
      </p>
    </div>
  )

对于上面的两个功能组件,我看到 TypeScript 生成了相同的 JS 代码。就可读性而言,PrintName2 组件对我来说似乎更加精简。我想知道这两种定义有什么区别,是否有人在使用第二种类型的 React 组件?

【问题讨论】:

在这里回答 ***.com/questions/44133420/… 更多关于你可以在 React.FC 中找到的属性。 harrymt.com/blog/2020/05/20/react-typescript-react-fc.html 【参考方案1】:

感谢大家的回答。他们是正确的,但我正在寻找更详细的版本。我做了更多研究,并在 GitHub 上的 React+TypeScript Cheatsheets 上找到了这个。

功能组件 这些可以写成普通函数,接受一个 props 参数并返回一个 JSX 元素。

type AppProps =  message: string ; /* could also use interface */

const App = ( message : AppProps) => <div>message</div>;

React.FC/React.FunctionComponent 呢? 您还可以使用React.FunctionComponent(或简写React.FC)编写组件:

const App: React.FC< message: string > = ( message ) => (
  <div>message</div>
);

与“正常功能”版本的一些区别:

它为 displayNamepropTypesdefaultProps 等静态属性提供类型检查和自动完成功能 - 但是,当前使用 defaultPropsReact.FunctionComponent 存在已知问题。有关详细信息,请参阅此 issue - 向下滚动到我们的 defaultProps 部分以在此处输入建议。

它提供了子项的隐式定义(见下文) - 但是隐式子项类型存在一些问题(例如,DefinitelyTyped#33006),无论如何,明确使用子项的组件可能被认为是一种更好的样式.

const Title: React.FunctionComponent< title: string > = (
  children,
  title
) => <div title=title>children</div>;

未来,它可能会自动将 props 标记为只读,但如果 props 对象在参数列表中被解构,那将是一个有争议的问题。

React.FunctionComponent 是明确的返回类型,而普通函数版本是隐式的(或者需要额外的注释)。

在大多数情况下,使用哪种语法几乎没有区别, 但是React.FC 语法稍微冗长一些,但没有提供 明显的优势,因此优先考虑“正常功能” 语法。

【讨论】:

嘿 Kuldeep,首先感谢您的详细回答。也许它缺少“有关详细信息,请参阅此问题”的链接。如果我记错了请忽略:) 嘿嘿,详细解释的链接是我第一段提到的github链接。 :) 谢谢【参考方案2】:

React.FC 不是输入 React 组件的首选方式,这里是 link。

我个人使用这种类型:

const Component1 = ( prop1, prop2 ): JSX.Element =>  /*...*/ 

React.FC 缺点的简短列表:

    提供子项的隐式定义,即使您的组件不需要有子项。这可能会导致错误。 不支持泛型。 不能与defaultProps 一起正常工作。

【讨论】:

如何输入检查 prop1、prop2 等? @ArafatZahan 你可以写 prop1, prop2 : prop1: string, prop2: number 。见***.com/questions/53329592/… prop1, prop2 : Props 如果你不使用 'children' 属性,请使用 React.VFC @KJSudarshan 很棒的笔记,应该有更多。点赞或回答【参考方案3】:

最佳解决方案:

第二种方法+一个返回类型

const PrintName2 = ( prop1, prop2 : Props): JSX.Element =>  /** */

这使您可以完全控制道具并且更加明确(没有隐藏的魔法)。

Link to GitHub PR to remove React.FC

Kent C Dodds has some thoughts why this is here

次优解:

第一个版本(React.FC)会为你添加一些类型——它们来自React Typings

interface FunctionComponent<P = > 
  (props: PropsWithChildren<P>, context?: any): ReactElement | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;

这种方法很有用有几个原因,但一个明显的原因是如果您的组件有子组件,那么您不需要手动添加 children 属性。这不是很好,因为默认 props 存在问题,而且许多组件没有子组件。

【讨论】:

【参考方案4】:

由于您使用 React 和 TypeScript,您应该始终使用第一种模式,因为它会确保您的组件具有更严格的类型,因为它暗示 PrintName 将是 React 功能组件类型,并且它包含Props 类型的道具。

const PrintName: React.FC<Props>

您可以阅读 React TypeScript 类型repository 上的功能组件的完整接口定义。

您提供的第二个示例不提供任何类型的类型,只是它是一个接受一组Props 类型参数的函数,并且它通常可以返回任何内容。

所以写

const PrintName2 = (props:Props)

类似于

const PrintName2: JSX.Element = (props:Props) 

因为 TypeScript 肯定无法自动推断它是一个功能组件。

【讨论】:

好的。但是应该推断第二种情况的返回类型。悬停在它上面显示如下: const PrintName2: (props: Props) => JSX.Element 虽然会被推断,但有时推断并不完全正确,而且如果在添加返回值之前先添加类型信息,则会出现错误直到遇到返回类型说明。 它可能会将其推断为 jsx 元素,但不会自动将其推断为功能组件 最佳答案,直截了当

以上是关于TypeScript React.FC<Props> 混淆的主要内容,如果未能解决你的问题,请参考以下文章

使用 typescript 中 Promise 中的值设置 React.FC 状态

React Typescript:在 React.FC 中设置状态以更改 React.Component 中的值

React.FC详细解说

ReactReact 组件

记一次Typescript+react的match的坑

React Router TypeScript 错误与Router