React Basics: Components, State, Events, and Forms
React simplifies UI development by using components, which are reusable functions that return JSX to structure applications efficiently. Events enable user interactions, while forms handle user input dynamically, ensuring a responsive interface. State manages component data, allowing updates and reactivity without reloading the page.1. Components
React applications are built using components, which are the fundamental building blocks of any React UI. A component is essentially a reusable piece of code (function) that returns JSX (HTML-like syntax). Components help in structuring and organizing a React application efficiently.
Key Features of React Components:- ♦ Reusability: Components can be used multiple times across the application.
- ♦ Separation of Concerns: Helps organize code by breaking UI into small, manageable parts.
- ♦ Encapsulation: Each component manages its own structure, logic, and styling.
- ♦ Composition: Components can be combined to form larger UI structures.
Basic Functional Component
Header.js (Encapsulation: Displays the Website Title)
function Header() {
return (
<header style={{ backgroundColor: "#007bff", color: "white", padding: "15px", textAlign: "center" }}>
<h1>My React Website</h1>
</header>
);
}
export default Header;
MainContent.js (Encapsulation: Handles Main Content)
function MainContent() {
return (
<main style={{padding: "20px", textAlign: "center", minHeight: "400px"}}>
<h2>Welcome to My Website</h2>
<p>This is a simple React app demonstrating component structure.</p>
</main>
);
}
export default MainContent;
Footer.js (Encapsulation: Displays the Footer)
function Footer() {
return (
<footer style={{ backgroundColor: "#333", color: "white", padding: "10px", textAlign: "center",
marginTop: "20px" }}>
<p>© 2024 My React Website. All rights reserved.</p>
</footer>
);
}
export default Footer;
Using the Component
App.js (Composition: Combines Header, MainContent, and Footer)In App.js
:
import Header from "./Header";
import MainContent from "./MainContent";
import Footer from "./Footer";
function App() {
return (
<div>
<Header />
<MainContent />
<Footer />
</div>
);
}
export default App;
Rendering a Component
Rendering a component means displaying a React component inside the browser. React does this by inserting the main component (App.js) into index.html via index.js.React renders components inside index.js
using ReactDOM.createRoot()
.
Example (index.js
)
import React from "react";
import ReactDOM from "react-dom/client"; // Loads ReactDOM, which handles rendering.
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />); // React renders App.js inside index.html
Understanding Props (Passing Data to Components) in React
Props (short for "properties") are a way to pass data from a parent component to a child component in React. They allow components to be dynamic and reusable by providing different values when needed.
Example:
Welcome.js: A component receives props as a function parameter.
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Default value for name if no prop is passed
Welcome.defaultProps = {
name: "Guest"
};
export default Welcome;
Passing Props to a Component:
App.js: let’s use <Welcome /> inside App.js and pass data.
import Welcome from "./Welcome"; // Import the Welcome component
function App() {
return (
<div>
<Welcome name="Alice" /> {/* Passing "Alice" as a prop */}
<Welcome name="Bob" /> {/* Passing "Bob" as a prop */}
<Welcome name="Charlie" /> {/* Passing "Charlie" as a prop */}
<Welcome /> {/* No name provided */}
</div>
);
}
export default App;
Props Are Read-Only
- ♦ Props are immutable—they cannot be changed inside the component.
- ♦ If you try to modify them, React will throw an error.
function Welcome(props) {
props.name = "John"; // ❌ This will cause an error
return Hello, {props.name}!
;
}
Passing Multiple Props
Props aren’t limited to just one value—you can pass multiple properties.UserCard.js:
function UserCard(props) {
return (
<div>
<h2>Name: {props.name}</h2>
<p>Age: {props.age}</p>
<p>Profession: {props.profession}</p>
</div>
);
}
export default UserCard;
Using UserCard in App.js:
import UserCard from "./UserCard";
function App() {
return (
<div>
<UserCard name="Alice" age={25} profession="Developer" />
<UserCard name="Bob" age={30} profession="Designer" />
<UserCard name="Charlie" age={35} profession="Manager" />
</div>
);
}
export default App;
2. State (Managing Component Data)
In React, state is used to manage dynamic data inside components. State allows a component to remember values between renders and update the UI when the state changes.What is useState?
useState is a React Hook that allows functional components to manage state. It returns two values:- 1. Current state value (count)
- 2. Function to update the state (setCount)
Example using useState
:
import { useState } from "react"; //useState is imported from React because it's a built-in Hook.
function Counter() {
const [count, setCount] = useState(0); //useState(0) initializes count with 0.
return (
<div style={{ textAlign: "center", marginTop: "20px" }}>
<h2>React Counter</h2>
<p>Count: {count}</p> {/*{count} dynamically displays the current state in the UI.*/}
<button onClick={() => setCount(count + 1)}>Increase</button>
{/*setCount(newValue) updates count and re-renders the component.*/}
{/*When the button is clicked, setCount(count + 1) increments the count by 1.*/}
<button onClick={() => setCount(count - 1)}>Decrease</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
export default Counter;
3. Handling Events in React
In React, event handling works similarly to JavaScript but with some key differences:- ♦ Event names use camelCase (onClick instead of onclick).
- ♦ Pass function references inside {} (not function calls).
- ♦ Prevent default behavior using event.preventDefault() (like preventing form submission).
Example 1: Handling Button Clicks
function App() {
function handleClick() {
alert("You clicked the button!");
}
return (
<div>
<h2>Click Event Example</h2>
<button onClick={handleClick}>Click Me</button>
</div>
);
}
export default App;
✅: onClick={handleClick} passes the function reference,
meaning React calls handleClick only when the button is clicked.
Example 2: Passing Parameters to Event Handlers
If you need to pass arguments inside an event handler, use an arrow function.
function App() {
function handleClick(name) {
alert(`Hello, ${name}!`);
}
return (
<button onClick={() => handleClick("Alice")}>
Click Me
</button>
);
}
export default App;
- ♦ () => handleClick("Alice") creates a new function that gets executed only when the button is clicked.
- ♦ This prevents handleClick("Alice") from running immediately.
Example 3: Handling Input Changes (onChange)
import { useState } from "react";
function App() {
const [text, setText] = useState("");
function handleChange(event) {
setText(event.target.value);
}
return (
<div>
<h2>Type something:</h2>
<input type="text" value={text} onChange={handleChange} />
<p>You typed: {text}</p>
</div>
);
}
export default App;
- ♦ onChange={handleChange} updates state when text is typed.
- ♦ event.target – Refers to the HTML element that triggered the event (e.g., an <input> field).
- ♦ event.target.value – Captures the current value of the input field
- ♦ setText(event.target.value); – Updates the state (text) with the new input value.
Example 4: Preventing Default Behavior (Form Submission)
Forms automatically reload the page when submitted. Prevent this using event.preventDefault().
import { useState } from "react";
function App() {
const [name, setName] = useState(""); // Stores name input
const [email, setEmail] = useState(""); // Stores email input
function handleSubmit(event) {
event.preventDefault(); // Prevents page reload
alert(`Name: ${name}\nEmail: ${email}`);
}
return (
<div style={{ textAlign: "center", marginTop: "20px" }}>
<h2>Simple Form</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Enter your name"
style={{ display: "block", margin: "10px auto", padding: "8px" }}
/>
<input
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
placeholder="Enter your email"
style={{ display: "block", margin: "10px auto", padding: "8px" }}
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;
Common Event Types in React
Event Type | Example Event Handler |
---|---|
Click | onClick={handleClick} |
Mouse Over | onMouseOver={handleMouseOver} |
Key Press | onKeyPress={handleKeyPress} |
Input Change | onChange={handleChange} |
Form Submit | onSubmit={handleSubmit} |
4. Conditional Rendering
Conditional rendering in React allows a component to display different content based on a condition (e.g., user login status, form completion, etc.).Example: Log In & Log Out Form with Username Validation
import { useState } from "react";
function LoginForm() {
const [isLoggedIn, setIsLoggedIn] = useState(false); // Controls login state
const [username, setUsername] = useState(""); // Stores username input
const [email, setEmail] = useState(""); // Stores email input
const [error, setError] = useState(""); // Stores validation error message
function isValidUsername(username) {
return /^[a-zA-Z0-9_]+$/.test(username); // Allows letters, numbers, and underscores only
}
function handleLogin(event) {
event.preventDefault(); // Prevent page reload
if (!username || !email) {
setError("Both fields are required.");
return;
}
if (!isValidUsername(username)) {
setError("Username can only contain letters, numbers, and underscores.");
return;
}
setError(""); // Clear errors if valid
setIsLoggedIn(true);
}
function handleLogout() {
setIsLoggedIn(false);
setUsername(""); // Clear input fields
setEmail("");
setError("");
}
return (
<div style={{ textAlign: "center", marginTop: "20px" }}>
<h2>{isLoggedIn ? `Welcome, ${username}!` : "Please Log In"}</h2>
{!isLoggedIn ? (
<form onSubmit={handleLogin}>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter your username"
style={{ display: "block", margin: "10px auto", padding: "8px" }}
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
style={{ display: "block", margin: "10px auto", padding: "8px" }}
/>
<button type="submit">Log In</button>
{/*Short-Circuit Evaluation*/}
{error && <p style={{ color: "red" }}>{error}</p>}
</form>
) : (
<button onClick={handleLogout}>Log Out</button>
)}
</div>
);
}
export default LoginForm;
This Login Form includes:
- ✅ Conditional rendering (isLoggedIn) controls which UI appears.
- ✅ Username field validation (no spaces or special characters).
- ✅ Two buttons: "Log In" (with validation) & "Log Out".
- ✅ State management: isLoggedIn controls which UI is displayed.
- ✅ Error messages if validation fails.
5. useEffect (Handling Side Effects)
What is useEffect?
useEffect is a React Hook that runs side effects in a component. A side effect is any operation that affects something outside the component, such as:- ✅ Fetching data from an API
- ✅ Updating the browser title
- ✅ Setting up event listeners
- ✅ Interacting with local storage
Example: Fetching Movies from an API
This example fetches a list of popular movies from the TMDB (The Movie Database) API.
import { useState, useEffect } from "react";
function MovieList() {
const [movies, setMovies] = useState([]); // State to store movie data
const [loading, setLoading] = useState(true); // State to track loading status
useEffect(() => {
fetch("https://api.tvmaze.com/shows") // Fetches a list of TV shows
.then((response) => response.json()) // Convert response to JSON
.then((data) => {
setMovies(data.slice(0, 10)); // Store only the first 10 movies
setLoading(false); // Stop loading
})
.catch((error) => console.error("Error fetching movie data:", error));
}, []); // Empty dependency array → Runs only once when the component mounts
return (
<div style={{ textAlign: "center", marginTop: "20px" }}>
<h2>Top 10 Movies</h2>
{loading ? (
<p>Loading...</p>
) : (
<ul style={{ listStyle: "none", padding: 0 }}>
{movies.map((movie) => (
<li key={movie.id} style={{ marginBottom: "15px", padding: "10px",
border: "1px solid #ddd" }}>
<strong>{movie.name}</strong> <br />
<img src={movie.image?.medium} alt={movie.name} style={{ borderRadius: "10px",
marginTop: "5px" }} />
<p><strong>Genre:</strong> {movie.genres.join(", ")}</p>
<p><strong>Premiered:</strong> {movie.premiered}</p>
</li>
))}
</ul>
)}
</div>
);
}
export default MovieList;
Structure of useEffect
useEffect(() => {
// Effect logic (e.g., fetching data)
}, [dependencies]);
- ♣ The first argument () => {} is the effect function.
- ♣ The second argument [dependencies] determines when the effect runs.
- ♣ Empty dependency array []: The effect runs only once, when the component mounts (i.e., on the first render).
movies.map((movie) => ())
Loops through movies and returns JSX for each movie.key={movie.id}
Ensures React efficiently updates the list.movie.image?.medium
- ♣ movie.image --> The image property inside the movie object.
- ♣ movie.image?.medium --> Accesses movie.image.medium, but only if movie.image exists.
- ♣ ?. (Optional Chaining) --> Prevents errors if image is null or undefined.