为什么React.FC被弃用了
来自github:merged pull request(Remove React.FC from Typescript template)
总结如下React.FC总共有几个缺点:
1.隐式地提供了一个children属性
const App: React.FC = () => { /*... */ };
const Example = () => {
<App><div>Unwanted children</div></App>
}
以上例子不会报错,在App
组件定义成React.FC
的时候,就包含了children
属性。即使你的本意是没有为App
提供children
属性,但是在Example
组件中显然不会报错。
2.不支持泛型
通常我们可以像定义函数的泛型一样定义React
的函数式组件,比如常用的Table
组件
type GenericComponentProps<T> = {
datasSource: T
column: ColumnProps<T>
}
const GenericComponent = <T>(props: GenericComponentProps<T>) => {/*...*/}
但是使用React.FC
的时候无能为力了
const GenericComponent: React.FC</* ??? */> = <T>(props: GenericComponentProps<T>) => {/*...*/}
3. 使组件作为命名空间的类型定义更困难
如下的例子
<Select>
<Select.Item />
</Select>
在React.FC
中定义Select
和Select.Items
的属性通常需要
const Select: React.FC<SelectProps> & { Item: React.FC<ItemProps> } = (props) => {/* ... */ }
Select.Item = (props) => { /*...*/ }
而是用自己的类型定义仅仅只需要
const Select = (props: SelectProps) => {/* ... */}
Select.Item = (props: ItemProps) => { /*...*/ }
4.不能正确的为defaultProps工作
当我们不使用React.FC
时,这样是可以正确的编译的。
type ComponentProps = { name: string; }
const Component = ({ name }: ComponentProps) => (<div>
{name.toUpperCase()} /* Safe since name is required */
</div>);
Component.defaultProps = { name: "John" };
const Example = () => (<Component />)
但如果使用React.FC
则会有问题:如果是使用React.FC<name: string>
将会使name
变成必传属性,
或者使用React.FC<name?: string>
则会使name.toUpperCase()
报一个类型错误。
* React.FC的好处
不过React.FC
也不是一无是处,他定义了一个返回的类型约束
const Component = () => {
return undefined; // 当这样返回类型时使用React.FC能快速捕捉错误
}
但是这并不能节省多少的工作量:
const Component1 = (props: ComponentProps): JSX.Element => { /*...*/ }
const Component2: FC<ComponentProps> = (props) => { /*...*/ }