Incorrectly mixing default exports and named exports can cause React to import the wrong thing (often undefined). The app may compile, but crash at runtime when React tries to render a component that isn’t actually a component. This often shows up as a runtime crash, so testing and lint rules are critical.
How can incorrect default vs named exports break a React application at runtime?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core idea
React doesn’t render “imports” — it renders the value you pass as a component. If you import the wrong symbol, you often end up with undefined (or a plain object). React then throws at runtime when it tries to treat that value like a component.
Export style | Import style | Typical runtime result | Fix |
|---|---|---|---|
Default export: | Wrong: | Button becomes | Use |
Named export: | Wrong: | Button becomes | Use |
Barrel re-export mistake | Import from | Import resolves but value is missing → | Fix barrel: export the symbol correctly |
Default export renamed during re-export |
| Named import is missing → | Re-export with a name: |
The classic crash
When React tries to render undefined as a component, you commonly see:Element type is invalid: expected a string (for built-in components) or a class/function but got: undefined
// Button.jsx
export default function Button() {
return <button>OK</button>;
}
// App.jsx (WRONG)
import { Button } from './Button';
export default function App() {
return <Button />; // Button === undefined -> runtime crash
}
// App.jsx (RIGHT)
import Button from './Button';
// Button.jsx
export function Button() {
return <button>OK</button>;
}
// App.jsx (WRONG)
import Button from './Button';
export default function App() {
return <Button />; // Button is not the named export -> undefined -> crash
}
// App.jsx (RIGHT)
import { Button } from './Button';
Why it can slip past “build success”
Depending on tooling (JS vs TS strictness, Babel settings, path aliases, barrel files), the import might not error at compile time. But at runtime, the imported value is still wrong (often undefined), and React only discovers it when rendering.
Quick debug step | What you’re checking | What it usually reveals |
|---|---|---|
Log the import |
| If you see |
Open the module file | Check the exact export statements | Whether it’s |
Check barrel/index files | Is the symbol re-exported correctly? | Missing or incorrectly named re-exports are common |
Search for duplicate files/paths | Same component name in multiple locations | You might be importing a different file than you think |
Best practice
Pick a team convention and enforce it with lint rules. Many teams prefer named exports for components (easier refactors + consistent imports), and reserve default exports for special cases (single main export modules). Consistency reduces these runtime failures.
Practical scenario
You import a component from a shared UI library and see "Element type is invalid" at runtime due to export mismatch.
Common pitfalls
- Mixing default and named exports in barrel files.
- Refactoring exports without updating all imports.
- Circular imports hiding the real error.
Named exports improve clarity but require consistent usage. Test with type checks and component render tests.