Full-project lesson · needs Node.js, npm and real project files, so it does not run in the in-page playground.
In a real project each component lives in its own file. You share components between files with JavaScript modules: export in one file and import in another. If modules are new to you, read JavaScript Modules and Export and Import first.
A component in its own file
Create the file src/components/Greeting.jsx:
function Greeting() {
return <p>Hello from its own file!</p>
}
export default Greeting
export default makes Greeting the main export of the file. Now import it in src/App.jsx:
import Greeting from './components/Greeting.jsx'
function App() {
return (
<main>
<h1>My React App</h1>
<Greeting />
</main>
)
}
export default App
The path starts with ./, which means “from this file’s folder”. The extension (.jsx) is included, as the Vite template does for App.jsx. Vite also resolves the import without the extension.
Default exports and named exports
There are two kinds of export, and you will see both.
Default export: one per file. You choose the name when you import.
// Button.jsx
export default function Button() {
return <button>Click</button>
}
// App.jsx
import Button from './Button.jsx'
Named export: many per file. You must import them by their exact name, in braces.
export function SaveButton() {
return <button>Save</button>
}
export function CancelButton() {
return <button>Cancel</button>
}
import { SaveButton, CancelButton } from './components/Buttons.jsx'
function App() {
return (
<div>
<SaveButton />
<CancelButton />
</div>
)
}
export default App
Which one should I use?
Both work. Pick one rule and keep it. A common approach: one component per file, default export, file name equal to the component name (Greeting.jsx exports Greeting). Named exports are handy for files that hold several small related components, and they make renaming safer because the name is checked on import.
Folder habits
src/
├── App.jsx
├── main.jsx
└── components/
├── Greeting.jsx
├── Buttons.jsx
└── Header.jsx
For bigger apps, see Organizing Components.
Common mistakes
- Importing a default export with braces.
import { Greeting } from ...givesundefinedfor a default export. Useimport Greeting from .... - Wrong path.
./Greeting.jsxand./components/Greeting.jsxare different files. Check the folder. - Case mismatch.
greeting.jsxandGreeting.jsxare different names on Linux servers, even if Windows hides it. Match the case exactly. - Forgetting
export. The error says the file “does not provide an export named …”. - A component file that also exports other things. The Oxlint rule in the template warns when a file exports components together with non-components, because it can break fast refresh.
Key points
- Put each component in its own file and share it with
exportandimport. - Default export:
import X from. Named export:import { X } from. - Keep file names, component names and your export style consistent.
Exercise: Move a component to its own file
You have a Footer component in App.jsx. Describe the steps to move it into src/components/Footer.jsx and use it again. —solution
- Create
src/components/Footer.jsxand move theFooterfunction into it. - Add
export default Footerat the bottom. - In
App.jsx, delete the function and addimport Footer from './components/Footer.jsx'at the top. - Keep using
<Footer />in the JSX. Check that the page still shows the footer.