React Basics: 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.
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)
When the state update function is called, React re-renders the component with the new state value.
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}`);
// Clear the inputs after submitting
setName("");
setEmail("");
}
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.