Welcome to my React Learning Journey! Here, I document useful tips, shortcuts, and best practices I discover along the way. This section will grow as I learn more. Enjoy the colorful notes and handy examples! 🚀
📚 Official React Docs (Beta):https://react.dev/learn
- JSX lets you write HTML-like code in JavaScript files.
- Babel compiles JSX to
React.createElementcalls. - JSX in React Docs
Example:
constelement=<h1>Hello, world!</h1>;- Use
ReactDOM.render(in older apps) or just return components in your app tree. - Rendering in React Docs
Example:
importReactfrom'react';importReactDOMfrom'react-dom/client';importAppfrom'./App';constroot=ReactDOM.createRoot(document.getElementById('root'));root.render(<App/>);- Default export:
exportdefaultApp;// import App from './App';
- Named export:
exportfunctionHeader(){}// import { Header } from './Header';
- You can have one default export and many named exports per file.
- Modules in React Docs
- Organize by feature or component.
- Common structure:
src/ components/ Header.js Footer.js App.js index.js styles/ App.css - Use PascalCase for component files:
MyComponent.js
- Use
{/* ... */}for JSX comments. - Use
//or/* ... */for JS comments.
Example:
// This is a JS comment{/* This is a JSX comment */}- Always add a unique
keyprop when rendering lists. - Lists & Keys in React Docs
Example:
{items.map(item=><likey={item.id}>{item.name}</li>)}- Use
<></>or<React.Fragment></React.Fragment>to group elements without adding extra nodes to the DOM. - Fragments in React Docs
Example:
return(<><h1>Title</h1><p>Description</p></>);Modern code editors like VS Code support handy shortcuts (snippets) for quickly scaffolding React components. Here are two of the most popular ones:
What it does:
- Generates a boilerplate for a React function component using an arrow function.
Example:
importReactfrom'react';constMyComponent=()=>{return(<div>
MyComponent
</div>);};exportdefaultMyComponent;How to use:
- Type
rfain a new.jsor.jsxfile and hitTab(if you have the ES7+ React/Redux/React-Native snippets extension installed in VS Code).
What it does:
- Generates a React function component using an arrow function and immediately exports it as default.
Example:
importReactfrom'react';constMyComponent=()=>{return(<div>
MyComponent
</div>);};exportdefaultMyComponent;How to use:
- Type
rafcand hitTab(with the same extension as above).
- State is a built-in object that stores property values that belong to a component.
- When state changes, the component re-renders to reflect those changes.
- State in React Docs
Use Case:
- Tracking user input, toggling UI elements, counters, form data, etc.
- Hooks are special functions that let you "hook into" React features (like state and lifecycle methods) in function components.
- Introduced in React 16.8, hooks allow you to use state and other React features without writing a class.
- Hooks in React Docs
Common Hooks:
useState— for state managementuseEffect— for side effects (like fetching data)useContext— for context API
What it does:
- Lets you add state to function components.
- useState in React Docs
Syntax:
const[state,setState]=useState(initialValue);Example: Counter
importReact,{useState}from'react';functionCounter(){const[count,setCount]=useState(0);return(<div><p>Count: {count}</p><buttononClick={()=>setCount(count+1)}>Add</button><buttononClick={()=>setCount(count-1)}>Subtract</button></div>);}How it works:
countis the current state value.setCountis the function to update the state.useState(0)sets the initial value to 0.
- The building block of any React app. Think of components as reusable, self-contained pieces of UI.
- Components in React Docs
Example:
functionWelcome(props){return<h1>Hello, {props.name}!</h1>;}// Usage:<Welcomename="Alice"/>- Props (short for "properties") are how you pass data from a parent component to a child component.
- Props are read-only in the child component.
- Props in React Docs
Example:
functionGreeting(props){return<p>Welcome, {props.user}!</p>;}<Greetinguser="Bob"/>childrenis a special prop that allows you to pass elements/components between the opening and closing tags of a component.- Children in React Docs
Example:
functionCard(props){return<divclassName="card">{props.children}</div>;}<Card><h2>Title</h2><p>This is inside the card!</p></Card>- Prop Drilling is the process of passing data from a parent component down to deeply nested child components via props, even if intermediate components don't need the data themselves.
- Prop Drilling in React Docs
Example:
functionGrandparent(){constmessage="Hello from Grandparent!";return<Parentmessage={message}/>;}functionParent(props){return<Childmessage={props.message}/>;}functionChild(props){return<p>{props.message}</p>;}Styling is a big part of building beautiful React apps. Here are all the main ways to style your components, with examples and tips!
- What: Traditional CSS files (e.g.,
App.css) imported at the top level. - Use Case: App-wide styles, resets, typography, colors.
Example:
/* App.css */body {
background:#f0f0f0;
font-family:'Segoe UI', sans-serif;
}import'./App.css';- What: Import a CSS file just for one component (e.g.,
Button.css). - Use Case: Styles that only apply to a specific component.
Example:
/* Button.css */
.button {
background:#007bff;
color: white;
border: none;
padding:8px16px;
border-radius:4px;
}import'./Button.css';functionButton(){return<buttonclassName="button">Click me</button>;}- What: Pass a
styleprop with a JS object. - Use Case: Quick, dynamic, or one-off styles.
Example:
functionBox(){return<divstyle={{background: 'yellow',padding: 20}}>Inline styled!</div>;}- What: Change styles based on state or props.
- Use Case: Highlight active items, show/hide, change color, etc.
Example:
functionToggle({ isActive }){return(<buttonstyle={{background: isActive ? 'green' : 'gray',color: 'white',}}>{isActive ? 'Active' : 'Inactive'}</button>);}- What: Locally scoped CSS files (e.g.,
Button.module.css). - Use Case: Avoids class name collisions, great for large apps.
Example:
/* Button.module.css */
.special {
color: orange;
font-weight: bold;
}importstylesfrom'./Button.module.css';functionButton(){return<buttonclassName={styles.special}>Module Button</button>;}- What: Use libraries (like
styled-components,emotion) to write CSS in JS files. - Use Case: Dynamic, themeable, and scoped styles with JS power.
Example (styled-components):
importstyledfrom'styled-components';constFancyButton=styled.button` background: hotpink; color: white; padding: 10px 20px; border: none; border-radius: 8px;`;functionApp(){return<FancyButton>Styled!</FancyButton>;}- Use CSS Modules or CSS-in-JS for large projects to avoid conflicts.
- Use global CSS for resets and base styles only.
- Use inline/dynamic styles for quick, state-based changes.
- Keep style logic close to the component it affects.
- Use BEM or similar naming for global classes.
- Global CSS: App-wide, imported once.
- Component CSS: Imported per component.
- Inline/Dynamic: For quick or state-based styles.
- CSS Modules: Scoped, avoids conflicts.
- Styled Components: Powerful, dynamic, and themeable.
Mix and match these techniques for beautiful, maintainable React apps! 🎨✨
- JSON (JavaScript Object Notation) is a lightweight data format for storing and transporting data.
- It's easy for humans to read and write, and easy for machines to parse and generate.
Example:
{
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "swimming"]
}- JSON Server is a full fake REST API that you can use for prototyping and mocking.
- It creates a REST API from a JSON file with zero configuration.
- Perfect for frontend development when you don't have a backend yet!
GitHub:github.com/typicode/json-server
Install globally:
npm install -g json-serverOr install locally:
npm install json-server --save-devCreate a db.json file:
{
"posts": [
{ "id": 1, "title": "First Post", "author": "John" },
{ "id": 2, "title": "Second Post", "author": "Jane" }
],
"comments": [
{ "id": 1, "body": "Great post!", "postId": 1 },
{ "id": 2, "body": "Nice work!", "postId": 2 }
],
"profile": {
"name": "John Doe"
}
}Start the server:
json-server --watch db.json --port 3001JSON Server automatically creates REST endpoints:
GET /posts- Get all postsGET /posts/1- Get post with id 1POST /posts- Create a new postPUT /posts/1- Update post with id 1PATCH /posts/1- Partially update post with id 1DELETE /posts/1- Delete post with id 1
Additional features:
GET /posts?_limit=10- Limit resultsGET /posts?_sort=title&_order=asc- Sort resultsGET /posts?title_like=react- Search (case-insensitive)GET /posts?_embed=comments- Include related data
Example: Fetching data
import{useState,useEffect}from'react';functionPosts(){const[posts,setPosts]=useState([]);useEffect(()=>{fetch('http://localhost:3001/posts').then(response=>response.json()).then(data=>setPosts(data));},[]);return(<div>{posts.map(post=>(<divkey={post.id}><h3>{post.title}</h3><p>By: {post.author}</p></div>))}</div>);}Example: Creating data
functionCreatePost(){const[title,setTitle]=useState('');consthandleSubmit=(e)=>{e.preventDefault();fetch('http://localhost:3001/posts',{method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({title: title,author: 'Anonymous'})}).then(response=>response.json()).then(data=>console.log('Created:',data));};return(<formonSubmit={handleSubmit}><inputvalue={title}onChange={(e)=>setTitle(e.target.value)}placeholder="Post title"/><buttontype="submit">Create Post</button></form>);}Custom port and host:
json-server --watch db.json --port 3001 --host 0.0.0.0Add to package.json scripts:
{
"scripts": {
"server": "json-server --watch db.json --port 3001"
}
}Then run:
npm run server- Prototyping: Quick API for frontend development
- Testing: Mock data for testing components
- Learning: Practice API calls without backend setup
- Demo: Showcase apps with realistic data
- JSON is a data format for storing and transporting data.
- JSON Server creates a full REST API from a JSON file.
- Perfect for frontend development and prototyping.
- Supports all CRUD operations and advanced queries.
JSON Server makes frontend development a breeze! 🚀✨
useEffectis a React Hook that lets you perform side effects in function components.- Side effects are operations like data fetching, subscriptions, or manually changing the DOM.
- useEffect in React Docs
When to use:
- API calls, timers, subscriptions, DOM manipulation, etc.
useEffect(()=>{// Side effect code here},[dependencies]);Parts:
- Effect function: The code that runs
- Dependency array: Controls when the effect runs
import{useEffect}from'react';functionUserProfile(){useEffect(()=>{console.log('Component mounted!');// Fetch user data, set up subscriptions, etc.},[]);// Empty array = run only oncereturn<div>User Profile</div>;}functionCounter(){const[count,setCount]=useState(0);useEffect(()=>{console.log('Count changed:',count);// This runs every time count changes});// No dependency array = run every renderreturn<buttononClick={()=>setCount(count+1)}>{count}</button>;}functionUserPosts({ userId }){const[posts,setPosts]=useState([]);useEffect(()=>{fetch(`/api/users/${userId}/posts`).then(response=>response.json()).then(data=>setPosts(data));},[userId]);// Runs when userId changesreturn<div>{posts.map(post=><divkey={post.id}>{post.title}</div>)}</div>;}- Cleanup prevents memory leaks by cleaning up subscriptions, timers, etc.
Example: Timer with Cleanup
functionTimer(){const[seconds,setSeconds]=useState(0);useEffect(()=>{constinterval=setInterval(()=>{setSeconds(prev=>prev+1);},1000);// Cleanup functionreturn()=>{clearInterval(interval);};},[]);// Empty array = run oncereturn<div>Seconds: {seconds}</div>;}Example: API Subscription
functionChatRoom({ roomId }){useEffect(()=>{constsubscription=subscribeToRoom(roomId);return()=>{subscription.unsubscribe();// Cleanup subscription};},[roomId]);return<div>Chat Room {roomId}</div>;}- Effect runs only once (on mount)
- Use for: Initial setup, one-time API calls
- Effect runs after every render
- Use carefully (can cause infinite loops)
- Effect runs when dependencies change
- Include all values from component scope that the effect uses
Example:
functionSearchResults({ query, filters }){useEffect(()=>{searchAPI(query,filters);},[query,filters]);// Runs when query OR filters change}functionUserList(){const[users,setUsers]=useState([]);const[loading,setLoading]=useState(true);useEffect(()=>{setLoading(true);fetch('/api/users').then(response=>response.json()).then(data=>{setUsers(data);setLoading(false);}).catch(error=>{console.error('Error:',error);setLoading(false);});},[]);if(loading)return<div>Loading...</div>;return<div>{users.map(user=><divkey={user.id}>{user.name}</div>)}</div>;}functionWindowSize(){const[size,setSize]=useState({width: 0,height: 0});useEffect(()=>{consthandleResize=()=>{setSize({width: window.innerWidth,height: window.innerHeight});};window.addEventListener('resize',handleResize);handleResize();// Set initial sizereturn()=>{window.removeEventListener('resize',handleResize);};},[]);return<div>Window size: {size.width} x {size.height}</div>;}- Always include dependencies that the effect uses
- Use cleanup functions for subscriptions, timers, event listeners
- Split effects by purpose (don't put unrelated logic in one effect)
- Use multiple effects instead of one complex effect
- Be careful with objects/arrays in dependencies (use useCallback/useMemo if needed)
// ❌ Missing dependencyuseEffect(()=>{setCount(count+1);},[]);// Should include 'count'// ❌ Infinite loopuseEffect(()=>{setCount(count+1);},[count]);// Creates infinite loop// ✅ Correct wayuseEffect(()=>{setCount(prev=>prev+1);},[]);// Use functional update- useEffect handles side effects in function components
- Dependency array controls when the effect runs
- Cleanup functions prevent memory leaks
- Use for: API calls, subscriptions, timers, DOM manipulation
Master useEffect to handle side effects like a pro! 🔄✨
- You can use
useEffectas many times as you want in a component. - Split effects by purpose: one for data fetching, one for subscriptions, etc.
Example:
useEffect(()=>{// Fetch data},[]);useEffect(()=>{// Set up event listenerreturn()=>{// Cleanup};},[]);- React Router is a popular library for handling navigation and routing in React applications. It allows you to display different components based on the URL, create navigation menus, and manage browser history.
- React Router v6 is the latest major version (as of 2024).
- Routes determine which component is rendered for a given URL path.
- You use the
<Routes>and<Route>components fromreact-router-dom.
Example:
import{BrowserRouter,Routes,Route}from'react-router-dom';importHomefrom'./Home';importAboutfrom'./About';importContactfrom'./Contact';functionApp(){return(<BrowserRouter><Routes><Routepath="/"element={<Home/>}/><Routepath="/about"element={<About/>}/><Routepath="/contact"element={<Contact/>}/></Routes></BrowserRouter>);}- The
pathprop sets the URL, andelementis the component to render.
- Use the
<Link>component to navigate between routes without reloading the page (SPA behavior).
Example:
import{Link}from'react-router-dom';functionNavbar(){return(<nav><Linkto="/">Home</Link><Linkto="/about">About</Link><Linkto="/contact">Contact</Link></nav>);}- The
toprop sets the destination path. Clicking aLinkupdates the URL and renders the corresponding component.
- Use
<NavLink>for navigation links that need to show an "active" style when the link matches the current URL.
Example:
import{NavLink}from'react-router-dom';functionNavbar(){return(<nav><NavLinkto="/"style={({ isActive })=>({fontWeight: isActive ? 'bold' : 'normal'})}>
Home
</NavLink><NavLinkto="/about"className={({ isActive })=>isActive ? 'active-link' : undefined}>
About
</NavLink><NavLinkto="/contact">
Contact
</NavLink></nav>);}- You can use the
styleorclassNameprop to apply styles when the link is active. - The
isActiveargument tells you if the link matches the current route.
// App.jsimport{BrowserRouter,Routes,Route,Link,NavLink}from'react-router-dom';functionHome(){return<h2>Home Page</h2>;}functionAbout(){return<h2>About Page</h2>;}functionContact(){return<h2>Contact Page</h2>;}functionNavbar(){return(<nav><NavLinkto="/"endstyle={({ isActive })=>({color: isActive ? 'red' : 'black'})}>
Home
</NavLink>{' | '}<NavLinkto="/about"style={({ isActive })=>({color: isActive ? 'red' : 'black'})}>
About
</NavLink>{' | '}<NavLinkto="/contact"style={({ isActive })=>({color: isActive ? 'red' : 'black'})}>
Contact
</NavLink></nav>);}functionApp(){return(<BrowserRouter><Navbar/><Routes><Routepath="/"element={<Home/>}/><Routepath="/about"element={<About/>}/><Routepath="/contact"element={<Contact/>}/></Routes></BrowserRouter>);}- useNavigate is a React Router hook that lets you navigate to different routes in your app using JavaScript code (not just by clicking links).
- This is useful for redirecting after a form submission, button click, or as a result of some logic.
import{useNavigate}from'react-router-dom';functionMyComponent(){constnavigate=useNavigate();functionhandleClick(){navigate('/about');// Go to the /about page}return<buttononClick={handleClick}>Go to About</button>;}- Calling
navigate('/about')changes the URL and renders the corresponding route.
- You can pass options to
navigate:replace: truereplaces the current entry in the history stack (like a redirect).navigate(-1)goes back one page (like browser back button).
Example:
navigate('/login',{replace: true});// Redirect to /login, replacing current pagenavigate(-1);// Go backimport{useNavigate}from'react-router-dom';functionLoginForm(){constnavigate=useNavigate();functionhandleSubmit(e){e.preventDefault();// ... authentication logic ...navigate('/dashboard');// Redirect to dashboard after login}return(<formonSubmit={handleSubmit}><inputtype="text"placeholder="Username"/><buttontype="submit">Login</button></form>);}- Route parameters (params) let you capture dynamic values from the URL and use them in your components. They are useful for things like user profiles, product pages, etc.
- Use a colon (
:) in thepathto define a param.
Example:
<Routes><Routepath="/users/:userId"element={<UserProfile/>}/></Routes>- Here,
:userIdis a route parameter. URLs like/users/42or/users/alicewill match.
- Use the
useParamshook fromreact-router-domto access params inside your component.
Example:
import{useParams}from'react-router-dom';functionUserProfile(){const{ userId }=useParams();return<h2>User ID: {userId}</h2>;}- The
useParamshook returns an object with all route params as strings.
<Routepath="/posts/:postId/comments/:commentId"element={<Comment/>}/>// In Comment component:const{ postId, commentId }=useParams();- Add a
?to make a param optional (React Router v6+):
<Routepath="/users/:userId?"element={<UserProfile/>}/>- For query strings like
?sort=asc&page=2, use theuseSearchParamshook.
Example:
import{useSearchParams}from'react-router-dom';functionProducts(){const[searchParams,setSearchParams]=useSearchParams();constsort=searchParams.get('sort');constpage=searchParams.get('page');return<div>Sort: {sort}, Page: {page}</div>;}- You can also update search params with
setSearchParams.
import{BrowserRouter,Routes,Route,useParams,useSearchParams}from'react-router-dom';functionUserProfile(){const{ userId }=useParams();return<h2>User ID: {userId}</h2>;}functionProducts(){const[searchParams]=useSearchParams();constsort=searchParams.get('sort')||'none';return<h2>Sort order: {sort}</h2>;}functionApp(){return(<BrowserRouter><Routes><Routepath="/users/:userId"element={<UserProfile/>}/><Routepath="/products"element={<Products/>}/></Routes></BrowserRouter>);}- Always wrap your app in
<BrowserRouter>(orHashRouterfor static hosting). - Use
<Routes>and<Route>for route definitions (v6+). - Use
<Link>or<NavLink>for navigation instead of<a>tags to avoid full page reloads. - The
endprop onNavLinkensures exact matching for the root path.
- Handling unknown routes is important for user experience. In React Router, you can show a custom 404 page when no route matches the current URL.
- Use a
path="*"route as the last<Route>to catch all unmatched URLs.
Example:
import{BrowserRouter,Routes,Route}from'react-router-dom';functionNotFound(){return<h2>404 - Page Not Found</h2>;}functionApp(){return(<BrowserRouter><Routes><Routepath="/"element={<Home/>}/><Routepath="/about"element={<About/>}/><Routepath="*"element={<NotFound/>}/></Routes></BrowserRouter>);}- The
path="*"route will match any URL that doesn't match a previous route, displaying theNotFoundcomponent.
- You can add navigation links, images, or custom styles to your 404 page.
Example:
functionNotFound(){return(<divstyle={{textAlign: 'center',marginTop: '2rem'}}><h1>404</h1><p>Sorry, the page you are looking for does not exist.</p><Linkto="/">Go Home</Link></div>);}- Nested routes let you render child components inside parent components based on the URL structure. This is useful for layouts, dashboards, and sections with sub-pages.
- Use a parent
<Route>with child<Route>s inside. The parent component should render an<Outlet />where child routes will appear.
Example:
import{BrowserRouter,Routes,Route,Outlet,Link}from'react-router-dom';functionDashboard(){return(<div><h2>Dashboard</h2><nav><Linkto="profile">Profile</Link> | <Linkto="settings">Settings</Link></nav><Outlet/>{/* Child routes render here */}</div>);}functionProfile(){return<h3>Profile Page</h3>;}functionSettings(){return<h3>Settings Page</h3>;}functionApp(){return(<BrowserRouter><Routes><Routepath="/dashboard"element={<Dashboard/>}><Routeindexelement={<DashboardHome/>}/><Routepath="profile"element={<Profile/>}/><Routepath="settings"element={<Settings/>}/></Route><Routepath="/"element={<Home/>}/></Routes></BrowserRouter>);}- Visiting
/dashboard/profileor/dashboard/settingswill render the corresponding child component insideDashboard.
- Use
indexto render a default child route when the parent path is matched exactly.
Example:
<Routepath="/dashboard"element={<Dashboard/>}><Routeindexelement={<DashboardHome/>}/><Routepath="profile"element={<Profile/>}/></Route>- Now
/dashboardshowsDashboardHomeby default.
- Use relative paths in
Link(e.g.,to="profile") for child routes.
import{BrowserRouter,Routes,Route,Outlet,Link}from'react-router-dom';functionDashboard(){return(<div><h2>Dashboard</h2><nav><Linkto="profile">Profile</Link> | <Linkto="settings">Settings</Link></nav><Outlet/></div>);}functionDashboardHome(){return<h3>Welcome to your dashboard!</h3>;}functionProfile(){return<h3>Profile Page</h3>;}functionSettings(){return<h3>Settings Page</h3>;}functionApp(){return(<BrowserRouter><Routes><Routepath="/dashboard"element={<Dashboard/>}><Routeindexelement={<DashboardHome/>}/><Routepath="profile"element={<Profile/>}/><Routepath="settings"element={<Settings/>}/></Route><Routepath="/"element={<h2>Home</h2>}/></Routes></BrowserRouter>);}useCallbackmemoizes a function so it only changes if its dependencies change.- Useful for optimizing performance, especially when passing callbacks to child components.
Example:
import{useCallback,useState}from'react';functionCounter(){const[count,setCount]=useState(0);constincrement=useCallback(()=>{setCount(c=>c+1);},[]);return<buttononClick={increment}>Count: {count}</button>;}- React supports all common DOM events:
onClick,onChange,onSubmit,onMouseOver, etc. - Event handlers are camelCase and receive an event object.
onClick Example:
functionButton(){consthandleClick=()=>{alert('Button clicked!');};return<buttononClick={handleClick}>Click me</button>;}onChange Example:
functionInput(){const[value,setValue]=useState('');return(<inputvalue={value}onChange={e=>setValue(e.target.value)}/>);}onSubmit Example:
functionForm(){consthandleSubmit=e=>{e.preventDefault();// Do something};return(<formonSubmit={handleSubmit}><buttontype="submit">Submit</button></form>);}- Use multiple
useEffects for different side effects. - Handle errors and loading for a better user experience.
- Custom hooks help you reuse logic.
useCallbackoptimizes performance for callbacks.- React events are camelCase and easy to use.
Master these patterns for robust, maintainable React apps! 🏆
- useLocation is a React Router hook that lets you access information about the current URL/location in your app.
- This is useful for reading the current path, search params, hash, or state passed during navigation.
import{useLocation}from'react-router-dom';functionShowLocation(){constlocation=useLocation();return(<div><p>Current pathname: {location.pathname}</p><p>Search string: {location.search}</p><p>Hash: {location.hash}</p><p>State: {JSON.stringify(location.state)}</p></div>);}- The
locationobject contains:pathname: The current path (e.g.,"/about")search: The query string (e.g.,"?sort=asc")hash: The hash fragment (e.g.,"#section1")state: Any state passed with navigationkey: Unique location key
import{useLocation}from'react-router-dom';functionSectionNav(){constlocation=useLocation();return(<nav><ahref="#section1"style={{fontWeight: location.hash==='#section1' ? 'bold' : 'normal'}}>Section 1</a><ahref="#section2"style={{fontWeight: location.hash==='#section2' ? 'bold' : 'normal'}}>Section 2</a></nav>);}import{useLocation,useNavigate}from'react-router-dom';functionSender(){constnavigate=useNavigate();return<buttononClick={()=>navigate('/target',{state: {from: 'Sender'}})}>Go</button>;}functionTarget(){constlocation=useLocation();return<div>Arrived from: {location.state?.from}</div>;}- index.js files are commonly used in folders to centralize and simplify imports/exports.
- They allow you to re-export multiple modules from a single entry point, making imports cleaner and more maintainable.
Suppose you have a folder structure like this:
/components
|-- Button.js
|-- Card.js
|-- Navbar.js
|-- index.js
Button.js
exportdefaultfunctionButton(){/* ... */}Card.js
exportdefaultfunctionCard(){/* ... */}Navbar.js
exportdefaultfunctionNavbar(){/* ... */}index.js (re-exporting all components)
export{defaultasButton}from'./Button';export{defaultasCard}from'./Card';export{defaultasNavbar}from'./Navbar';- Now you can import all components from the folder, not individual files:
import{Button,Card,Navbar}from'./components';- This is much cleaner, especially as your project grows.
- You can also re-export named exports from multiple files:
utils/math.js
exportfunctionadd(a,b){returna+b;}exportfunctionsubtract(a,b){returna-b;}utils/string.js
exportfunctioncapitalize(str){/* ... */}exportfunctiontoLower(str){/* ... */}utils/index.js
export*from'./math';export*from'./string';Now you can do:
import{add,subtract,capitalize}from'./utils';- index.js is automatically resolved by import statements targeting the folder.
- You can use
index.tsfor TypeScript projects. - This pattern is great for organizing components, hooks, utilities, and contexts.
- Avoid circular dependencies when re-exporting from multiple files.
- Centralizing your routes in a dedicated folder makes your app easier to maintain, scale, and organize, especially for larger projects.
- You can define all your route components and route definitions in one place, then import them into your main
App.jsormain.jsx.
/src
/components
/pages
/routes
|-- AppRoutes.js
|-- index.js
App.js
routes/AppRoutes.js
import{Routes,Route}from'react-router-dom';importHomefrom'../pages/Home';importAboutfrom'../pages/About';importDashboardfrom'../pages/Dashboard';importNotFoundfrom'../pages/NotFound';functionAppRoutes(){return(<Routes><Routepath="/"element={<Home/>}/><Routepath="/about"element={<About/>}/><Routepath="/dashboard/*"element={<Dashboard/>}/><Routepath="*"element={<NotFound/>}/></Routes>);}exportdefaultAppRoutes;routes/index.js
export{defaultasAppRoutes}from'./AppRoutes';App.js
import{BrowserRouter}from'react-router-dom';import{AppRoutes}from'./routes';functionApp(){return(<BrowserRouter><AppRoutes/></BrowserRouter>);}exportdefaultApp;- Keeps your main
App.jsclean and focused. - Makes it easy to add, remove, or update routes in one place.
- Encourages separation of concerns and better project structure.