Skip to content

React Tutorial Routing and Application Structure

Organizing React Components and Files

Lesson 111 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Full-project lesson · needs Node.js, npm and real project files, so it does not run in the in-page playground.

A folder structure cannot make code good, but a clear one saves time every day: new files have an obvious home, and old ones are easy to find. This lesson gives you simple rules that work for small and medium apps. Feature-Based Project Structure shows the next step for bigger ones.

Rule 1: one main component per file

Name the file after the component, in PascalCase:

code
PLAIN
Button.jsx        exports Button
ProductCard.jsx   exports ProductCard

Small helper components used only by one parent may share its file. If a helper grows, move it out.

Rule 2: group by kind (a good start)

A beginner-friendly layout groups files by what they are:

code
PLAIN
src/
├── main.jsx
├── App.jsx
├── components/        reusable UI pieces (Button, Modal, Card)
│   ├── Button.jsx
│   └── Modal.jsx
├── pages/             one component per route (Home, ProductPage)
│   ├── Home.jsx
│   └── ProductPage.jsx
├── hooks/             custom hooks (useLocalStorage)
│   └── useLocalStorage.js
├── utils/             plain JavaScript helpers (formatPrice)
│   └── formatPrice.js
├── api/               functions that call the server
│   └── products.js
└── assets/            images, fonts
FolderHoldsKnows about routes or data?
componentsGeneric, reusable UINo: gets everything through props
pages (or routes)The screen for each routeYes: reads params, loads data, composes components
hooksReusable stateful logicSometimes
utilsPure functions, no ReactNo
apiNetwork callsYes: URLs and data shapes

The key distinction is page vs component. A page is wired to the router and the data. A component just displays what it receives.

A component’s styles, tests and small private parts can sit next to it:

code
PLAIN
components/
└── Button/
    ├── Button.jsx
    ├── Button.module.css
    ├── Button.test.jsx
    └── index.js          // export { default } from './Button.jsx'

An index.js file lets you write import Button from './components/Button' instead of the longer path. Use this for components that have several files; for single files it only adds noise.

Rule 4: import carefully

Relative paths such as ../../../components/Button are hard to read and break when files move. Vite can define an alias, for example @ for src:

vite.config.js
JS
import path from 'node:path'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: { '@': path.resolve(import.meta.dirname, 'src') },
  },
})
App.jsx
JSX
import Button from '@/components/Button.jsx'

(With TypeScript, mirror the alias in tsconfig under paths.)

Rule 5: avoid cycles

If a.jsx imports b.jsx and b.jsx imports a.jsx, you get a circular dependency, which causes confusing “undefined” errors. Keep imports flowing one way: pages import components; components import utils; components should not import pages.

Rule 6: name things well

  • Components: nouns, ProductCard, CheckoutForm.
  • Hooks: start with use, useCart.
  • Handlers: handleClick; handler props: onClick.
  • Event and data files: products.js, formatPrice.js.
  • Booleans: isOpen, hasError.

Rule 7: do not over-split or over-plan

  • Do not create 30 folders for 5 files. Start flat and add structure when folders get crowded (roughly more than ten files).
  • Do not make a component “reusable” before you have a second use. Copy once, extract at the third time.
  • Moving files is cheap with an editor that updates imports, so improve the layout as you learn.

A small, verified example

This layout was built with Vite and tested in a browser. A page imports a reusable component, and a utility formats the price.

src/utils/formatPrice.js
JS
export function formatPrice(cents) {
  return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(cents / 100)
}
src/components/ProductCard.jsx
JSX
import { formatPrice } from '../utils/formatPrice.js'

function ProductCard({ name, priceCents }) {
  return (
    <article>
      <h2>{name}</h2>
      <p>{formatPrice(priceCents)}</p>
    </article>
  )
}

export default ProductCard
src/pages/Home.jsx
JSX
import ProductCard from '../components/ProductCard.jsx'

function Home() {
  return (
    <main>
      <h1>Shop</h1>
      <ProductCard name="Keyboard" priceCents={4950} />
    </main>
  )
}

export default Home
src/App.jsx
JSX
import Home from './pages/Home.jsx'

function App() {
  return <Home />
}

export default App

Key points

  • One main component per file, named after it; group by kind to start with.
  • Keep pages (routed, data-aware) apart from components (reusable, props-driven).
  • Use import aliases, avoid circular imports and add structure only when you need it.