简体   繁体   English

打字稿React.FC<Props> 困惑

[英]TypeScript React.FC<Props> confusion

I am learning TypeScript and some bits are confusing to me.我正在学习 TypeScript,有些东西让我感到困惑。 One bit is below:一位如下:

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>
  )
}

For both functional components above, I see TypeScript generates the same JS code.对于上面的两个功能组件,我看到 TypeScript 生成了相同的 JS 代码。 The PrintName2 component seems more streamlined to me as far as readability.就可读性而言, PrintName2组件对我来说似乎更加精简。 I wonder what's the difference between the two definitions and if anyone is using second type of React component?我想知道这两个定义之间有什么区别,是否有人在使用第二种类型的 React 组件?

Thanks all for the answers.谢谢大家的回答。 They are correct but I was looking for a more detailed version.他们是正确的,但我正在寻找更详细的版本。 I did some more research and found this on React+TypeScript Cheatsheets on GitHub.我做了更多的研究,并在 GitHub 上的React+TypeScript Cheatsheets上找到了这个。

Function Components功能组件
These can be written as normal functions that take a props argument and return a JSX element.这些可以写成普通函数,它们接受一个 props 参数并返回一个 JSX 元素。

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

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

What about React.FC / React.FunctionComponent ? React.FC / React.FunctionComponent怎么React.FunctionComponent You can also write components with React.FunctionComponent (or the shorthand React.FC ):您还可以使用React.FunctionComponent (或简写React.FC )编写组件:

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

Some differences from the "normal function" version:与“正常功能”版本的一些区别:

It provides typechecking and autocomplete for static properties like displayName , propTypes , and defaultProps - However, there are currently known issues using defaultProps with React.FunctionComponent .它为displayNamepropTypesdefaultProps等静态属性提供类型检查和自动完成 - 但是,当前存在将defaultPropsReact.FunctionComponent使用的已知问题。 See this issue for details - scroll down to our defaultProps section for typing recommendations there.有关详细信息,请参阅此问题- 向下滚动到我们的defaultProps部分以在那里输入建议。

It provides an implicit definition of children (see below) - however there are some issues with the implicit children type (eg DefinitelyTyped#33006), and it might be considered a better style to be explicit about components that consume children, anyway.它提供了子项的隐式定义(见下文)——但是,隐式子项类型存在一些问题(例如绝对类型#33006),无论如何,对于使用子项的组件进行显式显示可能被认为是一种更好的风格。

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

In the future, it may automatically mark props as readonly, though that's a moot point if the props object is destructured in the parameter list.将来,它可能会自动将 props 标记为只读,但如果 props 对象在参数列表中被解构,这是一个有争议的问题。

React.FunctionComponent is explicit about the return type, while the normal function version is implicit (or else needs additional annotation). React.FunctionComponent对返回类型是显式的,而普通函数版本是隐式的(否则需要额外的注解)。

In most cases, it makes very little difference which syntax is used, but the React.FC syntax is slightly more verbose without providing clear advantage, so precedence was given to the "normal function" syntax.在大多数情况下,使用哪种语法几乎没有区别,但是React.FC语法稍微冗长,没有提供明显的优势,因此优先考虑“普通函数”语法。

React.FC is not the preferable way to type a React component, here's a link . React.FC不是输入 React 组件的首选方式,这里有一个链接

I personally use this type:我个人使用这种类型:

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

Short list of React.FC cons: React.FC缺点的简短列表:

  1. Provides an implicit definition of children, even if your component doesn't need to have children.提供子项的隐式定义,即使您的组件不需要有子项。 That might cause an error.这可能会导致错误。
  2. Doesn't support generics.不支持泛型。
  3. Doesn't work correctly with defaultProps .不能与defaultProps一起正常工作。

Since you are using React and TypeScript, you should always use the first pattern, as it will ensure that your component is more strictly typed since it implies that the PrintName will be of type React Functional Component, and it takes in props of type Props .由于您使用的是 React 和 TypeScript,您应该始终使用第一种模式,因为它会确保您的组件类型更加严格,因为它意味着PrintName将是 React Functional Component 类型,并且它接受类型为Props props。

const PrintName: React.FC<Props>

You may read the full interface definition for Functional Components on the React TypeScript typings repository .您可以在 React TypeScript 类型存储库中阅读 Functional Components 的完整接口定义。

The second example you have provided does not provide any form of typings, except that it is a function that takes a set of parameters of type Props , and that it can return anything in general.您提供的第二个示例不提供任何形式的类型,只是它是一个函数,它采用一组Props类型的参数,并且它可以返回任何一般的东西。

Therefore, writing因此,写

const PrintName2 = (props:Props)

is akin to类似于

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

as TypeScript is definitely unable to automatically infer that it is a Functional Component.因为 TypeScript 肯定无法自动推断它是一个功能组件。

Best solution:最佳解决方案:

The second approach + a return type第二种方法+返回类型

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

This gives you complete control over the Props and is more explicit (there is no hidden magic).这使您可以完全控制道具并且更加明确(没有隐藏的魔法)。

Link to GitHub PR to remove React.FC链接到 GitHub PR 以删除 React.FC

Kent C Dodds has some thoughts why this is here Kent C Dodds 有一些想法为什么会在这里

Sub-optimal solution:次优解:

The first version (React.FC) will add a few types for you - they come from the React Typings第一个版本 (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;
}

This approach is useful for a few reasons but an obvious one is if your component has children, then you don't need to manually add a children prop.这种方法很有用,原因有几个,但一个明显的原因是如果您的组件有子组件,那么您不需要手动添加children It's not great because there are issues with default props and many components don't have children.这不是很好,因为默认道具存在问题并且许多组件没有子级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM