问题
代码如下:
import React from "react";
interface TestComponentProps {
hello: string;
}
const TestComponent: React.FC<TestComponentProps> = (props) => {
// 注意下面的children
const { hello, children } = props;
return <div className="TestComponent">{hello}</div>;
};
export default TestComponent;
如果你用的是React
18,那么会发现编辑器提示如下图(如果eslint配的非常严格,你的程序此时应该会报ts错误了):
你会发现, children
从props中消失了。
在固有认知中,用React.FC<TestComponentProps>
包起来的props
就应该天生具有一个可选的children
,但为什么在React
18不行了?
原因
这是因为ts类型定义导致。直接看18的ts定义源码:
// react 18+ FC类型定义
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
// 注意这一行的差别
(props: P, context?: any): ReactNode;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
那么,为什么16.8
和17
不会报这个错误呢?还是看源码:
// react 16.8 / 17 FC类型定义
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
// 注意这一行的差别
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
可以看出, FunctionalComponent
(即FC
)在18与16.8 / 17类型定义不完全相同,18将PropsWithChildren
移除了,即props
不会天生包含children
了,所以导致了上一部分的ts错误。
解决
重新定义一个补充类型即可:
import { PropsWithChildren, FC } from 'react';
export type RFC<T = unknown> = FC<PropsWithChildren<T>>;
然后在适当的时机import { RFC } from '@/your-type-file.ts';
,并且用RFC<IProps>
替代React.FC<IProps>
即可。