Dynamic Feature Loading with React Code Splitting
Code splitting is a crucial optimization technique for React applications, allowing you to break down your bundle into smaller chunks that are loaded on demand. This significantly improves initial load time and overall application performance, especially for larger applications with many components. This challenge asks you to implement dynamic code splitting in a React application using React.lazy and Suspense.
Problem Description
You are tasked with creating a React component that demonstrates code splitting. The component should initially render a loading indicator. When a button is clicked, it should dynamically load a separate module containing a specific component (e.g., HeavyComponent). The HeavyComponent represents a component that would typically be large and slow to load. You must use React.lazy to achieve this dynamic import and Suspense to handle the loading state.
What needs to be achieved:
- Create a parent component (
App) that contains a button. - Use
React.lazyto import a component (HeavyComponent) from a separate module (HeavyComponent.tsx). This module should be a separate file. - Wrap the lazy-loaded component with
Suspenseto display a fallback UI (loading indicator) while the component is being loaded. - When the button is clicked, the
HeavyComponentshould be dynamically loaded and rendered.
Key Requirements:
- The
HeavyComponentmust be in a separate file (HeavyComponent.tsx). - The
Appcomponent must useReact.lazyandSuspensecorrectly. - A loading indicator (e.g., a simple
<div>Loading...</div>) must be displayed whileHeavyComponentis loading. - The application should not load
HeavyComponentinitially.
Expected Behavior:
- The application initially renders the
Appcomponent with a button. - The
HeavyComponentis not loaded initially. - When the button is clicked, a loading indicator is displayed.
- After a short delay (simulating network latency), the
HeavyComponentis loaded and rendered, replacing the loading indicator.
Edge Cases to Consider:
- Error handling: While not explicitly required, consider how you might handle errors during the dynamic import process. (A simple
ErrorBoundarycould be used for this in a more complex scenario). - Loading state: Ensure the loading indicator is displayed correctly and disappears when the component is loaded.
Examples
Example 1:
Initial State: App component renders with a button labeled "Load Heavy Component". HeavyComponent is not loaded.
Input: User clicks the "Load Heavy Component" button.
Output: A loading indicator (e.g., "Loading...") is displayed. After a short delay, HeavyComponent is rendered below the button.
Explanation: React.lazy dynamically imports HeavyComponent, and Suspense displays the fallback while it loads.
Example 2:
Initial State: App component renders with a button labeled "Load Heavy Component". HeavyComponent is not loaded.
Input: User clicks the "Load Heavy Component" button multiple times.
Output: The loading indicator is displayed only once. Subsequent clicks do not trigger another load if HeavyComponent is already loaded.
Explanation: React.lazy caches the loaded module, so subsequent requests are served from the cache.
Constraints
- The
HeavyComponentmust be in a separate file namedHeavyComponent.tsx. - The application should be written in TypeScript.
- The loading indicator should be a simple
<div>element. - The dynamic import should be asynchronous.
- The
HeavyComponentshould simulate a slow load by introducing a short delay (e.g., 1-2 seconds) usingsetTimeoutwithin the component.
Notes
- Focus on the core concepts of
React.lazyandSuspense. - Consider using a functional component for
AppandHeavyComponent. - The
HeavyComponentdoesn't need to do anything complex; its primary purpose is to simulate a large component that takes time to load. - You can use any styling you prefer for the loading indicator.
- This challenge focuses on the loading mechanism; error handling is a secondary consideration.