# Loading Components This chapter will introduce how to use `createLazyComponent` to load and integrate remote React component modules in host applications. ## What is createLazyComponent? `createLazyComponent` is an API provided by React Bridge for loading individual remote components. Unlike `createRemoteAppComponent`, it is specifically designed for loading specific React components rather than complete applications. ### createLazyComponent vs createRemoteAppComponent | Feature | createLazyComponent | createRemoteAppComponent | | ------------------ | --------------------------------- | ------------------------------------------ | | **Use Case** | Load individual remote components | Load complete remote applications | | **Router Support** | ❌ No routing functionality | ✅ Complete router integration | | **Lifecycle** | ✅ Basic component lifecycle | ✅ Complete application lifecycle | | **Data Fetching** | ✅ Supports data fetching | ❌ Depends on application internal handling | | **SSR Control** | ✅ Controllable SSR | ❌ Determined by application | ## Installation ```sh [npm] npm install @module-federation/bridge-react@latest ``` ```sh [yarn] yarn add @module-federation/bridge-react@latest ``` ```sh [pnpm] pnpm add @module-federation/bridge-react@latest ``` ## Basic Usage ### Step 1: Register lazyLoadComponentPlugin Register the lazyLoadComponentPlugin plugin at runtime to enable createLazyComponent and prefetch APIs. ```tsx import { getInstance } from '@module-federation/runtime'; import { lazyLoadComponentPlugin } from '@module-federation/bridge-react'; const instance = getInstance(); // Register lazyLoadComponentPlugin plugin instance.registerPlugins([lazyLoadComponentPlugin()]); ``` ### Step 2: Call createLazyComponent After registering the `lazyLoadComponentPlugin` plugin, you can create lazy-loaded components using the `instance.createLazyComponent` method. ```tsx import { getInstance } from '@module-federation/runtime'; import { lazyLoadComponentPlugin } from '@module-federation/bridge-react'; const instance = getInstance(); // After registering lazyLoadComponentPlugin plugin, you can use `createLazyComponent` or `prefetch` APIs instance.registerPlugins([lazyLoadComponentPlugin()]); // Use instance.prefetch for remote module data prefetching instance.prefetch({ id: 'dynamic_remote' }); // Use instance.createLazyComponent for lazy loading remote modules const LazyComponent = instance.createLazyComponent({ loader: () => loadRemote('dynamic_remote'), loading: 'loading...', fallback: ({ error }) => { if (error instanceof Error && error.message.includes('not exist')) { return <div>fallback - not existed id</div>; } return <div>fallback</div>; }, }); ``` ## createLazyComponent API Reference ### Function Signature ```tsx function createLazyComponent<T, E extends keyof T>( options: CreateLazyComponentOptions<T, E> ): React.ComponentType<ComponentProps> ``` ### createLazyComponent > This API requires [registering the lazyLoadComponentPlugin plugin](#step-1-register-lazyloadcomponentplugin) first before it can be called.
  Type declaration```ts declare function createLazyComponent( props: CreateLazyComponentOptions ): (props: ComponentType) => React.JSX.Element; type CreateLazyComponentOptions<T, E extends keyof T> = { loader: () => Promise<T>; loading: React.ReactNode; delayLoading?: number; fallback: ReactNode | ((errorInfo: ErrorInfo) => ReactNode); export?: E; dataFetchParams?: DataFetchParams; noSSR?: boolean; injectScript?: boolean; injectLink?: boolean; }; type ComponentType = T[E] extends (...args: any) => any ? Parameters<T[E]>[0] extends undefined ? Record<string, never> : Parameters<T[E]>[0] : Record<string, never>; type DataFetchParams = { isDowngrade: boolean; } & Record<string, unknown>; type ErrorInfo = { error: Error; errorType: number; dataFetchMapKey?: string; }; ```
In addition to loading components, this function also supports the following capabilities: 1. In SSR mode, it will inject the corresponding producer's style tags/script resources, which can help avoid CSS flickering issues caused by streaming rendering and accelerate PID (First Paint Interactive Time). 2. If the producer has a data fetching function, it will automatically call this function and inject the data. ```tsx import React, { FC, memo, useEffect } from 'react'; import { getInstance } from '@module-federation/enhanced/runtime'; import { ERROR_TYPE } from '@module-federation/bridge-react'; const instance = getInstance(); const LazyComponent = instance.createLazyComponent({ loader: () => import('remote/Image'), loading: <div>loading...</div>, fallback: ({error,errorType,dataFetchMapKey}) => { console.error(error) if(errorType === ERROR_TYPE.LOAD_REMOTE){ return <div>load remote failed</div> } if(errorType === ERROR_TYPE.DATA_FETCH){ return <div>data fetch failed, the dataFetchMapKey key is: {dataFetchMapKey}</div> } return <div>error type is unknown</div>; }, }); const App: FC = () => { return <> <LazyComponent /> </>; }; export default App; ``` #### loader - Type: `() => Promise<T>` - Required: Yes - Default: `undefined` Function to load remote components, typically `()=>loadRemote(id)` or `()=>import(id)`. #### loading - Type: `React.ReactNode` - Required: Yes - Default: `undefined` Sets the module loading state. #### delayLoading - Type: `number` - Required: No - Default: `undefined` Sets the delay time for displaying loading state in milliseconds. If the loading time is less than this time, the loading state will not be displayed. #### fallback - Type: `(({ error }: { error: ErrorInfo}) => React.ReactElement)` - Required: Yes - Default: `undefined` The error component rendered when component **loading** or **rendering** fails. #### export - Type: `string` - Required: No - Default: `'default'` If the remote component is a named export, you can specify the component name to export through this parameter. By default, it loads the default export. #### dataFetchParams - Type: `DataFetchParams` - Required: No - Default: `undefined` If the remote component has a data fetching function, this will be passed to the data fetching function when set. #### noSSR - Type: `boolean` - Required: No - Default: `false` When set to `true`, this component will not render in SSR scenarios. #### injectScript - Type: `boolean` - Required: No - Default: `false` In SSR environment, if set to `true`, the created component will inject the corresponding script resources. For example, if `remote/button` has `__federation_button.js`, then in the HTML returned by SSR, the corresponding script will be injected before the component to accelerate interaction speed. ```html <script async src="__federation_button.js" crossOrigin="anonymous"/> <button>remote button</button> ``` #### injectLink - Type: `boolean` - Required: No - Default: `true` In SSR environment, if set to `true`, the created component will inject the corresponding style resource links. For example, if `remote/button` has `__federation_button.css`, then in the HTML returned by SSR, the corresponding link will be injected before the component to avoid page flickering issues. ```html <link href="__federation_button.css" rel="stylesheet" type="text/css"> <button>remote button</button> ``` ### prefetch > This API requires [registering the lazyLoadComponentPlugin plugin](#step-1-register-lazyloadcomponentplugin) first before it can be called.
  Type declaration```ts type PrefetchOptions = { id: string; dataFetchParams?: DataFetchParams; preloadComponentResource?: boolean; }; type DataFetchParams = { isDowngrade: boolean; _id?: string; } & Record<string, unknown>; ```
Preload component resource files and the component's data loader. ```ts import React, { FC, memo, useEffect } from 'react'; import { getInstance } from '@module-federation/enhanced/runtime'; const instance = getInstance(); instance.prefetch({ id: 'remote/Image', preloadComponentResource: true, }); ``` #### id - Type: `string` - Required: Yes - Default: `undefined` The id of the component to preload. #### preloadComponentResource - Type: `boolean` - Required: No - Default: `false` Whether to preload the component's resource files. #### dataFetchParams - Type: `DataFetchParams` - Required: No - Default: `undefined` If the remote component has a data fetching function, this will be passed to the data fetching function when set.