React动态导入组件时访问嵌套Loading组件的类型错误问题
解决动态导入React组件时无法访问嵌套Loading组件的TypeScript报错问题
问题场景
给函数组件PersonalDetailsForm添加了嵌套的Loading组件属性,常规导入时能正常访问,但使用dynamic动态导入时,TypeScript报错:
Property 'Loading' does not exist on type 'ComponentType<{}>'. Property 'Loading' does not exist on type 'ComponentClass<{}, any>'.
相关代码:
组件文件(personal-details-form.tsx)
const PersonalDetailsForm = () => <h1>Test</h1> const PersonalDetailsFormLoader = () => { return <>loading...</>; }; PersonalDetailsForm.Loading = PersonalDetailsFormLoader; export default PersonalDetailsForm
动态导入代码
const PersonalDetailsForm = dynamic(() => import("./personal-details-form"), { ssr: false, loading: () => <PersonalDetailsForm.Loading />, }); const loaders = [<TypeSelectionForm.Loading />, <PersonalDetailsForm.Loading />];
问题原因
TypeScript默认将动态导入的组件推断为ComponentType类型,这个类型并不包含我们自定义的Loading属性。而常规导入时,TypeScript能直接识别到组件上扩展的属性,所以不会报错。
解决方案
通过自定义类型扩展组件类型,明确声明组件包含Loading属性,让TypeScript正确识别。
方案1:在组件文件中定义自定义类型
修改personal-details-form.tsx,添加类型定义并断言组件类型:
import type { FC } from 'react'; // 定义包含Loading属性的组件类型 type PersonalDetailsFormType = FC & { Loading: FC; }; const PersonalDetailsForm = () => <h1>Test</h1> as PersonalDetailsFormType; const PersonalDetailsFormLoader = () => { return <>loading...</>; }; // 此时TypeScript能识别Loading属性 PersonalDetailsForm.Loading = PersonalDetailsFormLoader; export default PersonalDetailsForm;
在导入文件中指定动态导入的组件类型:
import dynamic from 'next/dynamic'; import type { PersonalDetailsFormType } from './personal-details-form'; const PersonalDetailsForm = dynamic( () => import("./personal-details-form").then((mod) => mod.default), { ssr: false, loading: () => <PersonalDetailsFormType.Loading />, } ) as unknown as PersonalDetailsFormType; // 现在可以正常访问Loading组件 const loaders = [<TypeSelectionForm.Loading />, <PersonalDetailsForm.Loading />];
方案2:单独导出Loading组件(更简单)
把Loading组件单独导出,避免在组件未加载时访问其嵌套属性:
// personal-details-form.tsx export const PersonalDetailsFormLoader = () => { return <>loading...</>; }; const PersonalDetailsForm = () => <h1>Test</h1>; PersonalDetailsForm.Loading = PersonalDetailsFormLoader; export default PersonalDetailsForm;
在导入文件中直接使用单独导出的Loading组件:
import dynamic from 'next/dynamic'; import { PersonalDetailsFormLoader } from './personal-details-form'; const PersonalDetailsForm = dynamic(() => import("./personal-details-form"), { ssr: false, loading: () => <PersonalDetailsFormLoader />, }); // 组件加载完成后也能正常访问嵌套的Loading属性 const loaders = [<TypeSelectionForm.Loading />, <PersonalDetailsForm.Loading />];
内容的提问来源于stack exchange,提问作者Netlemon Opp
相关产品推荐
相关产品推荐

