Table of Contents
- Prerequisites
- Setting Up Your Development Environment
- Understanding the React Project Structure
- Your First React Component: JSX and Rendering
- Components and Props: Reusability in Action
- State Management with
useState - Handling Events in React
- Styling Your React App
- Adding Routing with React Router
- Fetching Data from an API
- Testing Your React App
- Deploying Your React App
- Conclusion
- References
Prerequisites
Before diving in, ensure you have:
- Basic knowledge of HTML, CSS, and JavaScript: React builds on these fundamentals.
- Node.js and npm: React tools rely on Node.js (a JavaScript runtime) and npm (Node Package Manager). Download them from nodejs.org (LTS version recommended).
- Familiarity with ES6+ JavaScript: Concepts like arrow functions (
() => {}), destructuring (const { name } = user), and template literals (`Hello ${name}`) will simplify your React code.
Setting Up Your Development Environment
The easiest way to start a React project is with Create React App (CRA), a toolchain maintained by Facebook that sets up a modern React environment with zero configuration.
Step 1: Install Create React App
Open your terminal and run:
npx create-react-app my-first-react-app
npx(Node Package Runner) temporarily installs CRA to create your project, so you don’t need to install it globally.my-first-react-appis your project name (feel free to change it!).
Step 2: Navigate to Your Project and Start the Dev Server
cd my-first-react-app
npm start
This will launch a development server at http://localhost:3000. You’ll see a default React welcome page—congrats, your React app is running!
Understanding the React Project Structure
Let’s explore the key files and folders in your new project:
my-first-react-app/
├── node_modules/ # Dependencies (auto-generated)
├── public/ # Static files
│ ├── index.html # HTML entry point (React renders here)
│ ├── favicon.ico # Icon for your app
│ └── manifest.json # Metadata for progressive web apps (PWA)
├── src/ # Source code (where you’ll work!)
│ ├── App.css # Styles for App component
│ ├── App.js # Root component
│ ├── App.test.js # Tests for App component
│ ├── index.css # Global styles
│ ├── index.js # Renders React to the DOM
│ ├── logo.svg # Default React logo
│ └── reportWebVitals.js # Performance tracking (optional)
├── .gitignore # Files to ignore in Git
├── package.json # Project metadata and scripts
└── README.md # Project documentation
Key Files:
public/index.html: The only HTML file. React injects your app into the<div id="root"></div>element here.src/index.js: The JavaScript entry point. It imports React, ReactDOM, and yourAppcomponent, then rendersAppinto the DOM:import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );src/App.js: The root component of your app (we’ll modify this heavily!).
Your First React Component: JSX and Rendering
React apps are built with components—reusable, self-contained pieces of UI. Components can be functions or classes; we’ll focus on functional components (the modern, preferred approach).
What is JSX?
JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write HTML-like code within JavaScript. It’s not HTML, but a way to describe what the UI should look like.
Example JSX:
const element = <h1>Hello, React!</h1>;
JSX is transpiled (converted) to regular JavaScript by tools like Babel, which is included in CRA.
Modifying the App Component
Let’s replace the default App.js with a simpler component. Open src/App.js and update it:
import './App.css';
function App() {
return (
<div className="App">
<h1>Welcome to My First React App! 🚀</h1>
<p>This is a simple React frontend built from scratch.</p>
</div>
);
}
export default App;
function App(): This is a functional component (a JavaScript function that returns JSX).className: In JSX, useclassNameinstead ofclass(sinceclassis a reserved keyword in JavaScript).- Save the file—the dev server will auto-reload, and you’ll see your new content at
http://localhost:3000.
Components and Props: Reusability in Action
Components become powerful when you can reuse them with different data. Props (short for “properties”) let you pass data from a parent component to a child component.
Step 1: Create a Reusable Component
Let’s build a UserCard component that displays a user’s name, role, and avatar. Create a new folder src/components and add UserCard.js:
// src/components/UserCard.js
function UserCard(props) {
return (
<div className="user-card">
<img src={props.avatar} alt={props.name} />
<h3>{props.name}</h3>
<p>Role: {props.role}</p>
</div>
);
}
export default UserCard;
Here, props is an object containing the data passed to UserCard.
Step 2: Use the Component with Props
Now, import UserCard into App.js and use it with different props:
import './App.css';
import UserCard from './components/UserCard';
function App() {
return (
<div className="App">
<h1>Our Team 👥</h1>
<div className="user-cards">
<UserCard
name="Alice Smith"
role="Frontend Developer"
avatar="https://i.pravatar.cc/150?img=1"
/>
<UserCard
name="Bob Johnson"
role="Backend Developer"
avatar="https://i.pravatar.cc/150?img=2"
/>
</div>
</div>
);
}
export default App;
Step 3: Add Styling (Optional)
To make the cards look better, add styles to src/App.css:
/* src/App.css */
.App {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.user-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.user-card {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.user-card img {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
}
Now your app will display two styled user cards with unique data!
State Management with useState
State is data that changes over time and affects your component’s rendering. Unlike props (which are passed from parents and immutable), state is managed inside a component and can be updated.
React provides hooks—special functions—to add state to functional components. The most basic hook is useState.
Example: Building a Counter
Let’s create a Counter component that increments a number when a button is clicked.
- Create
src/components/Counter.js:
import { useState } from 'react';
function Counter() {
// Initialize state: [currentState, setState] = useState(initialValue)
const [count, setCount] = useState(0);
return (
<div className="counter">
<h2>Counter: {count}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;
useState(0): Initializes thecountstate to0.setCount: A function to updatecount(never modify state directly, e.g.,count++).onClick: React event handler (note the camelCase:onClickinstead ofonclick).
- Import
CounterintoApp.jsand use it:
import './App.css';
import UserCard from './components/UserCard';
import Counter from './components/Counter';
function App() {
return (
<div className="App">
<h1>My React App Features 🎯</h1>
<Counter />
{/* ... UserCard code ... */}
</div>
);
}
Click the “Increment” button—the counter will update!
Handling Events in React
React events (like onClick, onChange, onSubmit) work similarly to HTML events but with camelCase syntax and require functions as handlers.
Example: Form Input with onChange
Let’s add a form that updates state as the user types. Create src/components/SearchBar.js:
import { useState } from 'react';
function SearchBar() {
const [searchTerm, setSearchTerm] = useState('');
const handleChange = (e) => {
setSearchTerm(e.target.value); // e.target.value is the input text
};
return (
<div className="search-bar">
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
/>
<p>You searched for: {searchTerm}</p>
</div>
);
}
export default SearchBar;
value={searchTerm}: Binds the input’s value to thesearchTermstate (controlled component).onChange={handleChange}: UpdatessearchTermwhenever the input changes.
Styling Your React App
React offers multiple styling approaches. Here are the most common:
1. Inline Styles
Quick for small components, but not ideal for large apps:
<div style={{ color: 'blue', fontSize: '20px' }}>Hello</div>
2. CSS Files
Global styles (e.g., src/index.css) or component-specific styles (e.g., UserCard.css). Import the CSS file into your component:
import './UserCard.css';
3. CSS Modules (Scoped Styles)
To avoid style conflicts, use CSS Modules (built into CRA). Rename UserCard.css to UserCard.module.css:
/* UserCard.module.css */
.userCard {
border: 1px solid #e0e0e0;
/* ... */
}
Import and use it in UserCard.js:
import styles from './UserCard.module.css';
function UserCard(props) {
return <div className={styles.userCard}>...</div>;
}
Class names are scoped to the component (e.g., userCard becomes UserCard_userCard__abc123).
Adding Routing with React Router
Single-Page Applications (SPAs) like React apps use client-side routing to navigate without reloading the page. Use react-router-dom for this.
Step 1: Install React Router
npm install react-router-dom
Step 2: Set Up Routes
Create src/pages for route components: Home.js, About.js, Contact.js.
Home.js:
function Home() {
return <h1>Home Page 🏠</h1>;
}
export default Home;
About.js:
function About() {
return <h1>About Us ℹ️</h1>;
}
export default About;
Step 3: Configure Routing in App.js
Update App.js to use React Router:
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import './App.css';
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link> |
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Router>
);
}
export default App;
Router: Wraps your app to enable routing.Link: Replaces<a>tags for client-side navigation.RoutesandRoute: Define which component to render for each URL path.
Fetching Data from an API
Most apps need to fetch data from a backend API. Use the fetch API or libraries like axios with React’s useEffect hook (runs side effects, like data fetching).
Example: Fetching Users from JSONPlaceholder
JSONPlaceholder is a free fake API for testing. Let’s fetch and display a list of users.
Create src/components/UserList.js:
import { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Fetch data when the component mounts
fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => {
if (!res.ok) throw new Error('Failed to fetch users');
return res.json();
})
.then((data) => {
setUsers(data);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, []); // Empty dependency array: runs once on mount
if (loading) return <p>Loading users...</p>;
if (error) return <p>Error: {error}</p>;
return (
<div className="user-list">
<h2>Users from API</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name} ({user.email})</li>
))}
</ul>
</div>
);
}
export default UserList;
useEffect: Runs the fetch call after the component renders.key: Required for lists in React to identify items uniquely.
Testing Your React App
CRA includes Jest (testing framework) and React Testing Library (for rendering components) out of the box.
Example: Testing the Counter Component
Open src/components/Counter.test.js and write a test:
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('increments counter when button is clicked', () => {
render(<Counter />);
const counterElement = screen.getByText(/counter:/i);
const button = screen.getByText(/increment/i);
expect(counterElement).toContainElement(screen.getByText('0'));
fireEvent.click(button);
expect(counterElement).toContainElement(screen.getByText('1'));
});
Run tests with:
npm test
Deploying Your React App
Once your app is ready, deploy it to share with the world!
Step 1: Build the Production Version
CRA generates an optimized build:
npm run build
This creates a build/ folder with static HTML/CSS/JS files.
Step 2: Deploy to Vercel (Free)
- Push your code to GitHub.
- Sign up for Vercel and connect your GitHub repo.
- Vercel will auto-detect your React app and deploy it!
Conclusion
You’ve built a React frontend from scratch! You now understand:
- Component creation and reusability with props.
- State management with
useState. - Event handling and form inputs.
- Routing with React Router.
- Data fetching with
useEffectand APIs. - Styling and deployment.
React’s ecosystem is vast—next, explore state management libraries like Redux or Context API, or dive into advanced hooks like useReducer and useRef.