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:

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

❌ Incorrect (Trying to Modify Props)
        
            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:

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:

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;
        
    

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;
        
    

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:

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:

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]);
        
    

movies.map((movie) => ())

Loops through movies and returns JSX for each movie.

key={movie.id}

Ensures React efficiently updates the list.

movie.image?.medium