我正在学习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组件?
5条答案
按热度按时间o4tp2gmn1#
谢谢大家的回答。他们是正确的,但我正在寻找一个更详细的版本。我做了更多的研究,并在GitHub上的React+TypeScript Cheatsheets上找到了这个。
功能组件
这些可以写成普通函数,接受props参数并返回JSX元素。
什么是
React.FC
/React.FunctionComponent
?您也可以使用React.FunctionComponent
(或简写React.FC
)编写组件:与“正常功能”版本的一些区别:
它为
displayName
、propTypes
和defaultProps
等静态属性提供了类型检查和自动完成功能-但是,目前已知将defaultProps
与React.FunctionComponent
一起使用时存在问题。详细信息请参阅本期-向下滚动到我们的defaultProps
部分,在那里输入建议。它提供了一个隐式的子类型定义(见下文)-但是隐式子类型存在一些问题(例如:DefinitelyTyped#33006),而且无论如何,明确使用子级的组件可能被认为是一种更好的样式。
将来,它可能会自动将props标记为readonly,尽管如果props对象在参数列表中被破坏结构化,那么这一点就没有实际意义了。
React.FunctionComponent
是显式的返回类型,而普通函数版本是隐式的(否则需要额外的注解)。在大多数情况下,使用哪种语法差别很小,但
React.FC
语法稍微冗长一些,没有明显的优势,因此优先考虑“普通函数”语法。bzzcjhmw2#
React.FC
不是输入React组件的首选方式,这里是link。我个人使用这种类型:
React.FC
缺点列表:1.提供子级的隐式定义,即使组件不需要子级。这可能会导致错误。
1.不支持泛型。
1.不能正确使用
defaultProps
。s4n0splo3#
最佳方案:
第二种方法+一个返回类型
这让你可以完全控制 prop ,而且更明确(没有隐藏的魔法)。
Link to GitHub PR to remove React.FC
Kent C Dodds has some thoughts why this is here
次优方案:
第一个版本(React.FC)将为您添加一些类型-它们来自React Typings
这种方法很有用,原因有几个,但一个明显的原因是,如果您的组件有子组件,那么您就不需要手动添加
children
属性。这不是很好,因为默认 prop 存在问题,许多组件没有子组件。wqlqzqxt4#
因为你使用的是React和TypeScript,所以你应该总是使用第一种模式,因为它会确保你的组件是更严格的类型,因为它意味着
PrintName
将是React Functional Component类型,并且它接受Props
类型的props。你可以在React TypeScript类型库中阅读Functional Components的完整接口定义。
您提供的第二个示例没有提供任何形式的类型,除了它是一个接受一组
Props
类型的参数的函数,并且它可以返回任何一般的东西。因此,写作
类似于
因为TypeScript肯定无法自动推断它是一个功能组件。
oaxa6hgo5#
不要再使用React.FC了。人们过去使用React.FC的原因是因为它在你的 prop 中添加了更多的类型,比如孩子。
在您代码示例中,您不需要子级,因此只需像这样编写
但最终会遇到的问题是,您希望将子项传递给组件,而首选的方式如下
使用React.PropsWithChildren进行扩展与您输入的内容相同:
React.PropsWithChildren也可以传递一个泛型,但默认值是未知的。如果你愿意,你可以像这样设置孩子,但是除非你确定你只想要一个特定的类型,否则我只会使用默认值。
并传入组件中所需的子级类型。
您不必传递JSX.Element的返回类型,因为它是推断的。