Table of Contents
- Prerequisites
- Setting Up Your Development Environment
- Understanding React Project Structure
- Core React Concepts
- Building a Simple Project: Todo App
- Styling Your React App
- Testing Your Application
- Deploying Your React App
- Troubleshooting Common Issues
- Conclusion
- References
Prerequisites
Before diving into React, ensure you have basic knowledge of:
- HTML/CSS: To structure and style your UI.
- JavaScript (ES6+): Familiarity with concepts like arrow functions (
() => {}), destructuring,let/const, template literals, and modules will help. - Command Line: Basic commands like
cd,mkdir, andnpm/yarn(we’ll usenpmhere).
You’ll also need:
- Node.js and npm: React tooling relies on Node.js. Download it from nodejs.org (LTS version recommended). npm (Node Package Manager) is included with Node.js.
Setting Up Your Development Environment
The easiest way to start a React project is with Create React App (CRA), an official tool 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
npxis a tool that runs packages without installing them globally.create-react-appis the package name.my-first-react-appis your project name (replace with your preferred name).
Step 2: Navigate to the Project Folder
cd my-first-react-app
Step 3: Start the Development Server
Run the app locally:
npm start
This will launch a development server at http://localhost:3000. You’ll see a default React page with a spinning logo. Any changes you make to your code will auto-refresh the page (hot reloading).
Understanding React Project Structure
Let’s explore the key files and folders in your my-first-react-app directory:
my-first-react-app/
├── node_modules/ # Dependencies (auto-generated)
├── public/ # Static files (HTML, images, etc.)
│ ├── index.html # Main HTML file (React injects UI here)
│ └── favicon.ico # Icon for the browser tab
├── src/ # Source code (where you’ll write most of your code)
│ ├── App.css # Styles for App component
│ ├── App.js # Root component
│ ├── App.test.js # Tests for App component
│ ├── index.css # Global styles
│ ├── index.js # Entry point (renders App into index.html)
│ ├── logo.svg # Default React logo
│ └── reportWebVitals.js # For measuring performance
├── .gitignore # Files to ignore in Git (e.g., node_modules)
├── package.json # Project metadata and dependencies
└── README.md # Project documentation
public/index.html: The only HTML file. React renders components into the<div id="root"></div>element here.src/index.js: The “entry point” of your app. It usesReactDOM.createRootto render theAppcomponent into the root div.src/App.js: The root component. All other components will be nested insideApp.
Core React Concepts
Components
React apps are built with components—reusable, self-contained pieces of UI. Think of components as building blocks (e.g., buttons, forms, cards).
There are two types of components:
- Functional Components: JavaScript functions that return React elements.
- Class Components: ES6 classes that extend
React.Component(less common now; functional components with hooks are preferred).
We’ll focus on functional components (the modern approach).
Example: A Simple Functional Component
Create a new file src/Welcome.js:
// Welcome.js
function Welcome() {
return <h1>Hello, React Beginner!</h1>;
}
export default Welcome;
To use this component in App.js, import it:
// App.js
import Welcome from './Welcome';
function App() {
return (
<div className="App">
<Welcome /> {/* Render the Welcome component */}
</div>
);
}
export default App;
Save the files, and you’ll see “Hello, React Beginner!” on localhost:3000.
JSX: JavaScript XML
JSX is a syntax extension for JavaScript that looks like HTML. It lets you write HTML-like code directly in your JavaScript files.
Key JSX Rules:
- Use
classNameinstead ofclass(sinceclassis a reserved word in JavaScript). - Self-close tags (e.g.,
<img />,<input />). - Wrap multi-line JSX in parentheses
(). - Embed JavaScript expressions with
{}:function Greeting() { const name = "Alice"; return <h1>Hello, {name}!</h1>; // Renders "Hello, Alice!" }
Props: Passing Data to Components
Props (short for “properties”) let you pass data from a parent component to a child component. They are read-only (children can’t modify props).
Example: Using Props
Update Welcome.js to accept a name prop:
// Welcome.js
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
export default Welcome;
Pass the name prop from App.js:
// App.js
<Welcome name="Bob" /> {/* Renders "Hello, Bob!" */}
You can also destructure props for cleaner code:
function Welcome({ name }) { // Destructure the "name" prop
return <h1>Hello, {name}!</h1>;
}
State: Managing Dynamic Data
State is used to manage data that changes over time (e.g., form inputs, toggle switches). Unlike props, state is private to a component and can be modified.
To use state in functional components, we use the useState hook (a built-in function from React).
Example: Counter with State
Create src/Counter.js:
import { useState } from 'react'; // Import useState
function Counter() {
// Initialize state: count = 0, setCount = function to update count
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;
useState(0)initializescountto0.setCountis a function that updatescount(never modify state directly, e.g.,count = count + 1won’t work).onClickis an event handler that triggerssetCountwhen the button is clicked.
Import Counter into App.js to see it in action!
Event Handling
React events are similar to HTML events but use camelCase (e.g., onClick, onChange) and require function references (not strings).
Example: Form Input with State
function NameInput() {
const [name, setName] = useState("");
const handleChange = (e) => {
setName(e.target.value); // Update state with input value
};
return (
<div>
<input
type="text"
value={name} // "Controlled component": value tied to state
onChange={handleChange} // Triggered on input change
placeholder="Enter your name"
/>
<p>Hello, {name}!</p>
</div>
);
}
This is a controlled component—the input’s value is managed by React state.
Conditional Rendering
Render different content based on state or props using JavaScript conditionals (e.g., if/else, ternary operators).
Example: Ternary Operator
function UserGreeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<h1>Welcome back!</h1>
) : (
<h1>Please sign in.</h1>
)}
</div>
);
}
// Usage: <UserGreeting isLoggedIn={true} />
Lists and Keys
To render lists of items, use the map method. Each item in the list needs a unique key prop to help React identify changes efficiently.
Example: Rendering a List
function TodoList() {
const todos = ["Learn React", "Build an app", "Deploy"];
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li> // Use index as key (ok for static lists)
))}
</ul>
);
}
Note: For dynamic lists (e.g., todos that can be added/removed), use unique IDs instead of indexes as keys (e.g., key={todo.id}).
Building a Simple Project: Todo App
Let’s apply these concepts to build a todo app with:
- A form to add todos.
- A list to display todos.
- The ability to delete todos.
Step 1: Set Up State for Todos
In App.js, we’ll manage the list of todos in state:
// App.js
import { useState } from 'react';
import './App.css';
function App() {
const [todos, setTodos] = useState([]); // Empty array to hold todos
const [input, setInput] = useState(""); // State for input field
return (
<div className="App">
<h1>Todo App</h1>
{/* Form and list will go here */}
</div>
);
}
export default App;
Step 2: Create the Todo Form
Add a form to capture user input and add todos:
// Inside App.js's return statement
<form
onSubmit={(e) => {
e.preventDefault(); // Prevent default form submission
if (input.trim()) { // Don't add empty todos
setTodos([...todos, input]); // Add new todo to the array
setInput(""); // Clear input field
}
}}
>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add a new todo..."
/>
<button type="submit">Add</button>
</form>
Step 3: Render the Todo List
Add a list to display todos, with a delete button for each:
// Inside App.js's return statement (below the form)
<ul>
{todos.map((todo, index) => (
<li key={index}>
{todo}
<button onClick={() => {
// Create a new array without the todo at "index"
const newTodos = todos.filter((_, i) => i !== index);
setTodos(newTodos);
}}>
Delete
</button>
</li>
))}
</ul>
Step 4: Add Styling
Update src/App.css to make it look cleaner:
/* App.css */
.App {
max-width: 500px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input {
flex: 1;
padding: 8px;
font-size: 16px;
}
button {
padding: 8px 16px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px;
margin: 5px 0;
background: #f8f9fa;
border-radius: 4px;
}
li button {
background: #dc3545;
}
Your todo app should now let you add and delete todos!
Styling Your React App
Beyond basic CSS, React supports multiple styling approaches:
- CSS Modules: Scoped styles (e.g.,
Todo.module.css). - Styled Components: CSS-in-JS (write CSS in JavaScript).
- Tailwind CSS: Utility-first framework.
For simplicity, we used global CSS in our todo app. To try CSS Modules:
- Rename
App.csstoApp.module.css. - Import it as
import styles from './App.module.css'. - Use classes like
className={styles.App}.
Testing Your Application
React includes a test runner (Jest) and testing library (React Testing Library) out of the box. To run tests:
npm test
A basic test for App.js (in App.test.js) checks if the app renders correctly:
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders todo app heading', () => {
render(<App />);
const headingElement = screen.getByText(/Todo App/i);
expect(headingElement).toBeInTheDocument();
});
Deploying Your React App
To share your app with others, deploy it! Here’s how to deploy to Netlify (free):
Step 1: Build the App
Create an optimized production build:
npm run build
This generates a build/ folder with static files.
Step 2: Deploy to Netlify
- Push your code to GitHub (create a repo and commit/push).
- Go to netlify.com and sign up.
- Click “New site from Git” → Select your GitHub repo.
- Set build command:
npm run build - Set publish directory:
build - Click “Deploy site”.
Your app will be live at a Netlify URL (e.g., https://your-app-name.netlify.app).
Troubleshooting Common Issues
- Component Not Rendering: Check for typos in component names or import paths.
- State Not Updating: Ensure you’re using
setState/useStatecorrectly (never mutate state directly). - Props Not Passing: Verify the parent is passing props and the child is receiving them (use
console.log(props)to debug). - JSX Errors: Ensure tags are closed and multi-line JSX is wrapped in
().
Use the React DevTools browser extension to inspect components, props, and state in real time.
Conclusion
You’ve built your first React app! We covered components, JSX, props, state, events, and deployment. React’s power lies in its simplicity and flexibility—start small, experiment, and gradually explore advanced topics like hooks (useEffect, useContext), routing, and state management (Redux, Zustand).
Keep practicing by adding features to your todo app (e.g., edit todos, mark as complete) or building new apps (weather app, blog).