Import on Interaction: Load When User Interacts
Import on Interaction is a performance pattern that uses dynamic import() to load non-critical code only when the user explicitly interacts with a UI element. It reduces initial JavaScript bundle size while deferring cost to the moment of actual need. Combine with prefetching on hover/focus and Promise caching for smooth UX.
Static imports = pre-cooking everything before the restaurant opens. Import on Interaction = cooking expensive dishes only after the customer orders them. You save kitchen resources upfront, but the first order might take slightly longer unless you start prep on early signals like seeing the menu (hover/focus).
1Basic Click Pattern
Load the module only when the user clicks. Cache the result so subsequent clicks are instant.
const handleOpen = async () => {
if (!Modal) {
const mod = await import('./SettingsModal');
setModal(() => mod.default);
}
setOpen(true);
};2Prefetch on Hover / Focus
Start loading on early intent signals (mouseenter, focus) to hide network latency before the actual click.
<button
onMouseEnter={prefetch}
onFocus={prefetch}
onClick={handleClick}
>
Open Chat
</button>3Promise Caching
Cache the import Promise to avoid duplicate requests and simplify loading state management.
let modalPromise;
function loadModal() {
if (!modalPromise) modalPromise = import('./Modal');
return modalPromise;
}4React Hook Pattern
Encapsulate loading, caching, states, and prefetching into a reusable hook for clean component code.
| Property | Eager / Static Import | Import on Interaction |
|---|---|---|
| Behavior | Loaded during initial bundle | Loaded only on user action |
| Use Case | Core features needed on first paint | Optional, heavy, secondary features |
| Bundle Impact | Increases initial JS size | Smaller initial bundle |
| Interaction Latency | Zero (already loaded) | Small delay on first use |
Eager / Static Import
Behavior
Loaded during initial bundle
Use Case
Core features needed on first paint
Bundle Impact
Increases initial JS size
Interaction Latency
Zero (already loaded)
Import on Interaction
Behavior
Loaded only on user action
Use Case
Optional, heavy, secondary features
Bundle Impact
Smaller initial bundle
Interaction Latency
Small delay on first use
Common questions
- ›“How would you implement lazy loading on user interaction?”
- ›“What is the difference between lazy loading on mount vs on interaction?”
- ›“How do you reduce perceived latency when using import on interaction?”
- ›“When is this pattern a good idea vs a bad idea?”
What interviewers look for
- Clear distinction between lazy-on-mount and true intent-driven loading
- Understanding of Promise caching and prefetch strategies
- Awareness of UX tradeoffs and loading states
- Realistic candidate selection (good vs bad features)
Short answer (60 sec)
Import on interaction triggers dynamic import() on explicit user actions like clicks. It reduces initial bundle size by moving non-critical code off the startup path while using hover/focus prefetching and Promise caching to minimize first-use delay.
Detailed answer (senior level)
This pattern builds on dynamic import() to create intent-driven code splitting. Load on click for safety, prefetch on hover/focus for better responsiveness, and always cache the Promise. Good candidates are heavy optional features (modals, editors, charts). The main tradeoff is moving cost from startup to first interaction — manage it with loading UI, error handling, and careful feature selection. Senior answers include reusable hooks and performance measurement.
- Loading on mount (useEffect) instead of real user interaction
- No loading states or feedback on first click
- Not caching the Promise → duplicate network requests
- Deferring critical path or tiny modules
- Ignoring mobile (no hover) and error handling
- ✓Import on interaction defers heavy optional code until explicit user intent
- ✓Combine click loading with hover/focus prefetching for smoother UX
- ✓Always cache the import Promise to avoid redundant work
- ✓Provide clear loading and error states
- ✓Best for modals, editors, charts, admin tools — not core navigation
- ✓Measure both initial bundle reduction and interaction-to-ready latency