美文网首页
React v18+ 中 React.FC读取children报

React v18+ 中 React.FC读取children报

作者: 拜仁的月饼 | 来源:发表于2024-01-15 16:46 被阅读0次

    问题

    代码如下:

    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;
    

    如果你用的是React18,那么会发现编辑器提示如下图(如果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.817不会报这个错误呢?还是看源码:

    // 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>即可。

    相关文章

      网友评论

          本文标题:React v18+ 中 React.FC读取children报

          本文链接:https://www.haomeiwen.com/subject/snshodtx.html