打字稿React.FC <Props>混乱

时间:2020-01-30 14:52:54

标签: javascript reactjs typescript frontend

我正在学习打字稿,有些地方让我感到困惑。以下是一位:

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组件。

4 个答案:

答案 0 :(得分:18)

谢谢大家的回答。他们是正确的,但我正在寻找更详细的版本。我进行了更多研究,并在github上的react-typescipt速查表上找到了这一点:https://github.com/typescript-cheatsheets/react-typescript-cheatsheet#reacttypescript-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>
);

与“正常功能”版本有所不同:

它为displayName,propTypes和defaultProps之类的静态属性提供类型检查和自动完成功能-但是,当前存在将defaultProps与React.FunctionComponent一起使用的已知问题。有关详细信息,请参见此问题-向下滚动到我们的defaultProps部分,以在其中键入建议。

它提供了子代的隐式定义(请参阅下文)-但是隐式子代类型存在一些问题(例如DefinitelyTyped#33006),并且无论如何,它可能认为更好的样式对于使用儿童的组件是明确的。 / p>

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

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

React.FunctionComponent关于返回类型是显式的,而普通函数版本是隐式的(否则需要附加注释)。

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

答案 1 :(得分:14)

React.FC不是键入React组件的首选方法,有link

我个人使用这种类型:

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

React.FC缺点的简短列表:

  1. 提供子级的隐式定义。即使您的组件不需要孩子,也可能会导致错误。
  2. 不支持泛型。
  3. 不能与defaultProps一起正常使用。

答案 2 :(得分:3)

第一个版本将为您添加一些类型-它们来自React.FC

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

这出于几个原因很有用,但很明显的一个原因是您的组件是否有子级。然后,您无需手动添加儿童道具

答案 3 :(得分:2)

由于您使用的是React和TypeScript,因此您应始终使用第一种模式,因为这将确保您的组件的输入更为严格,因为这意味着PrintName的类型将是React Functional Component,并且接受Props类型的道具。

const PrintName: React.FC<Props>

您可以在React TypeScript类型为repository的情况下阅读功能组件的完整接口定义。

您提供的第二个示例不提供任何形式的键入,只是它是一个带有一组Props类型的参数的函数,并且它可以返回任何常规值。

因此,写作

const PrintName2 = (props:Props)

类似于

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

因为TypeScript绝对无法自动推断出它是一个功能组件。

相关问题