Week 7: React 1

INFO 253A: Front-end Web Architecture

Kay Ashaolu

React Chapter 1: Introduction to the Course

Intro

  • Welcome to "React Front to Back"!
  • Understand front-end web architecture through React
  • Course objectives and learning outcomes

What is Front-End Web Architecture?

  • Structure and organization of the user-facing part of web applications
  • Key components:
    • User Interface (UI)
    • Client-Side Logic
    • Communication with Back-End Services
  • Importance of modularity and scalability

Evolution of Front-End Development

  • Transition from static pages to dynamic applications
  • Rise of JavaScript frameworks and libraries
  • Challenges in managing complex UIs
  • Need for efficient state management and component reusability

Introducing React

  • A JavaScript library for building user interfaces
  • Created and maintained by Facebook
  • Enables building UIs from small, reusable components
  • Focuses on declarative programming

Component-Based Architecture

  • Break down UI into reusable components
  • Each component encapsulates:
    • Structure (HTML/JSX)
    • Logic (JavaScript)
    • Styling (CSS)
  • Benefits:
    • Reusability
    • Maintainability
    • Testability

Understanding JSX

  • JavaScript XML: Combines HTML and JavaScript
  • Allows writing HTML-like syntax in JavaScript files
  • Enhances readability and ease of writing components
const element = <h1>Hello, world!</h1>;

State and Props

  • State:
    • Internal data of a component
    • Determines component behavior and rendering
  • Props (Properties):
    • External data passed to components
    • Makes components dynamic and configurable

Virtual DOM and Performance

  • React maintains a virtual representation of the UI
  • Efficiently updates and renders components
  • Minimizes direct manipulation of the actual DOM
  • Results in improved performance and user experience

Set up Dev Enviroment

Tools and technologies:

  • Node.js and NPM:
    • JavaScript runtime and package manager
  • Create React App:
    • Tool to bootstrap React applications
  • Text Editor:
    • Recommended: Visual Studio Code
  • Version Control with Git:
    • Essential for tracking changes and collaboration
  • React Developer Tools:
    • Browser extension for debugging React apps

Setting Up the Development Environment: Prerequisites

  • Node.js installed on your machine
    • Verify by running node -v in your terminal
  • Familiarity with basic command-line operations
  • A code editor (e.g., Visual Studio Code)

Installing Create React App

  • Use Create React App to bootstrap your project
  • Run the following command in your terminal:
 npx create-react-app feedback-app --use-npm
  • Navigate into your project directory:
 cd feedback-app

Starting the Development Server

  • Launch the app in development mode:
 npm start

Understanding the Project Structure

  • package.json:
    • Lists dependencies like react, react-dom, and react-scripts
    • Contains scripts for starting, building, and testing your app
  • public/ directory:
    • Contains index.html
    • This is the single page loaded in the browser
    • <div id="root"></div> acts as a placeholder for our React app

Understanding the Project Structure

  • src/ directory:
    • Contains all React components and application logic
    • Entry point is index.js

Examining index.html

  • Located in the public/ folder
  • Simplify by removing unnecessary comments
  • Change the <title> to your app's name:
 <title>Feedback UI</title>
  • The <div id="root"></div> is crucial
    • React will render the entire app inside this div

Cleaning Up the Initial Setup

Removing Unnecessary Files

  • In the src/ directory, delete all files:
 src/
 └── (empty)
  • This allows us to start from scratch and understand each part we add
  • You'll see an error in the browser since index.js is missing

Creating Essential Files

  • index.js:
 import React from 'react';
 import ReactDOM from 'react-dom';
 import App from './App';

 ReactDOM.render(
   <React.StrictMode>
     <App />
   </React.StrictMode>,
   document.getElementById('root')
 );

Creating Essential Files

  • App.js:
 function App() {
   return (
     <h1>Hello from the App component</h1>
   );
 }

 export default App;
  • index.css (optional for global styles)

Initialization: Understanding index.js

  • Entry Point of the React application
  • Imports:
 import React from 'react';
 import ReactDOM from 'react-dom';
 import App from './App';

Initialization: Understanding index.js

  • Renders the App component into the DOM:
 ReactDOM.render(
   <React.StrictMode>
     <App />
   </React.StrictMode>,
   document.getElementById('root')
 );
  • Wraps <App /> with <React.StrictMode> for additional checks and warnings

Creating the App Component

  • Functional Component defined as a JavaScript function
  • Returns JSX to be rendered:
 function App() {
   return (
     <h1>Hello from the App component</h1>
   );
 }
  • Must be exported to be used in other files:
 export default App;

What is JSX?

  • JavaScript XML
  • Syntax extension that allows writing HTML-like code in JavaScript
  • Makes it easier to create React elements
  • Transpiled to React.createElement() calls under the hood

Rules of JSX

  • Must return a single parent element
    • Wrap sibling elements in a <div> or <> (fragment)
  • Use camelCase for HTML attributes
    • className instead of class
    • htmlFor instead of for
  • Can embed JavaScript expressions inside { }

Example of JSX

function App() {
  const title = 'Feedback UI';
  return (
    <div className="container">
      <h1>{title}</h1>
      <p>Collect feedback from users.</p>
    </div>
  );
}

Dynamic Values and Expressions

  • Use { } to embed variables and expressions
  • Examples:
 const user = 'Alice';

 return (
   <h1>Hello, {user}!</h1>
 );
<p>The sum is: {2 + 3}</p>  // Outputs: The sum is: 5
  • Can call functions or methods:
 <h1>{title.toUpperCase()}</h1>

Conditional Rendering

  • Using Ternary Operator:
 const isLoggedIn = true;

 return (
   <div>
     {isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign in.</h1>}
   </div>
 );
  • Using Logical AND (&&) Operator:
 const hasNotifications = true;

 return (
   <div>
     {hasNotifications && <p>You have new messages.</p>}
   </div>
 );

Displaying Data with map()

  • Iterate over arrays to render lists
  • Example:
 const feedbackItems = [
   { id: 1, text: 'Great product!' },
   { id: 2, text: 'Could be improved.' },
   { id: 3, text: 'Excellent support.' },
 ];

 return (
   <ul>
     {feedbackItems.map((item) => (
       <li key={item.id}>{item.text}</li>
     ))}
   </ul>
 );
  • Key Prop:
    • Important for React's reconciliation process
    • Should be a unique identifier (like id)

Attribute Differences

  • class becomes className
 <div className="container">
   {/* ... */}
 </div>
  • for becomes htmlFor
 <label htmlFor="email">Email:</label>
  • Event handlers use camelCase:
 <button onClick={handleClick}>Click Me</button>

Common Pitfalls

  • Avoid using index as key when items can be reordered
  • Ensure the key is unique among siblings
  • Do not use duplicate keys

Differences Between HTML and JSX

Self-Closing Tags

  • In JSX, some elements must be self-closed
  • Examples:
 <img src="image.png" alt="Example" />
 <input type="text" />
  • Cannot have empty tags like <div></div> without content
    • Can use <div /> if it's empty

React Chapter 3: Components, Props, and State

Creating Your First Component

  • Components are the building blocks of a React application.
  • Functional Components: JavaScript functions that return JSX.
  • Example:
 function Header() {
   return <h1>Feedback UI</h1>;
 }

Using JSX in Components

  • JSX allows you to write HTML-like syntax in JavaScript.
  • Example:
 return (
   <header>
     <div className="container">
       <h2>Feedback UI</h2>
     </div>
   </header>
 );

Importing and Exporting Components

  • Use export to make components available to other files.
  • Use import to bring components into a file.
  • Example:
 import Header from './components/Header';

Props in React Components

  • Props are inputs to components (similar to function arguments).
  • Pass props like HTML attributes.
  • Example:
 <Header text="Hello World" />

Accessing Props in a Component

  • Receive props as a parameter in the component function.
  • Destructure props for cleaner code.
  • Example:
 function Header({ text }) {
   return <h2>{text}</h2>;
 }

Default Props and PropTypes

  • Default Props: Define default values for props.
  • PropTypes: Typechecking for props.
  • Example:
 Header.defaultProps = {
   text: 'Feedback UI',
 };

 Header.propTypes = {
   text: PropTypes.string,
 };

Adding Styles to a Component

  • Styles can be added using CSS classes or inline styles.
  • Inline Styles: Use the style attribute with a JavaScript object.
  • Example:
 const headerStyles = {
   backgroundColor: 'blue',
   color: 'red',
 };

 return <header style={headerStyles}>...</header>;

Conditional Styling with Props

  • Use props to conditionally apply styles.
  • Example:
 function Card({ children, reverse }) {
   return (
     <div className={`card ${reverse && 'reverse'}`}>
       {children}
     </div>
   );
 }

The useState Hook

  • State: Data that changes over time in a component.
  • useState is a Hook that lets you add state to functional components.
  • Example:
 const [rating, setRating] = useState(7);

 // Updating state
 setRating(10);

Handling Events

  • Use event handlers like onClick to respond to user interactions.
  • Example:
 <button onClick={() => setRating((prev) => prev + 1)}>
   Increase Rating
 </button>

Managing Global State

  • Component State: Local to a component.
  • Global State: Shared across multiple components.
  • Store global state in a higher-level component and pass it down via props.
  • Example:
 const [feedback, setFeedback] = useState(FeedbackData);

Mapping Lists to Components

  • Use map to render lists of data as components.
  • Example:
 feedback.map((item) => (
   <FeedbackItem key={item.id} item={item} />
 ));

Passing Functions as Props

  • Functions can be passed as props to handle events in child components.
  • Example:
 <FeedbackItem handleDelete={deleteFeedback} />

Lifting State Up

  • Move state up to the nearest common ancestor to share between components.
  • Enables communication between sibling components via props.

Conditional Rendering

  • Render components or elements conditionally using JavaScript logic.
  • Example:
 {feedback.length === 0 ? (
   <p>No Feedback Yet</p>
 ) : (
   feedback.map((item) => <FeedbackItem ... />)
 )}

Creating a Card Component

  • Create reusable components for styling.
  • Wrap content inside the Card component.
  • Example:
 function Card({ children }) {
   return <div className="card">{children}</div>;
 }

Events and Prop Drilling

  • Prop Drilling: Passing props through multiple levels to reach a child component.
  • Can lead to less maintainable code.
  • Alternative solutions include Context API or state management libraries.

Deleting Items from State

  • Use state setter functions to update state immutably.
  • Example:
 const deleteFeedback = (id) => {
   setFeedback(feedback.filter((item) => item.id !== id));
 };

Feedback Stats Component

  • Calculate and display statistics based on state data.
  • Example:
 function FeedbackStats({ feedback }) {
   // Calculate average
   return (
     <div className="feedback-stats">
       <h4>{feedback.length} Reviews</h4>
       <h4>Average Rating: {average}</h4>
     </div>
   );
 }

Calculating Averages

  • Use array methods like reduce to compute aggregate data.
  • Example:
 let average =
   feedback.reduce((acc, cur) => acc + cur.rating, 0) /
   feedback.length;

Formatting Numbers in JavaScript

  • Use toFixed and replace to format numbers.
  • Example:
 average = average.toFixed(1).replace(/[.,]0$/, '');

Handling No Data States

  • Provide default UI when there's no data to display.
  • Example:
 if (!feedback || feedback.length === 0) {
   return <p>No Feedback Yet</p>;
 }

The React Dev Tools

  • Browser extension to inspect React component hierarchies.
  • View state and props for each component.

Importing Assets and CSS

  • Import CSS files directly in your components.
  • Example:
 import './index.css';

Example of Prop Drilling

Scenario

Imagine we have a simple React application with the following component hierarchy:

  • App
    • ParentComponent
      • ChildComponent

We want to share a piece of state (e.g., a counter) between ParentComponent and ChildComponent. To achieve this, we'll lift the state up to the App component and pass it down via props, which can lead to prop drilling.

Lifting State Up

Lifting state up involves moving state to a common ancestor so that it can be shared among multiple components.

Example:

App.js

import React, { useState } from 'react';
import ParentComponent from './ParentComponent';

function App() {
  const [counter, setCounter] = useState(0);

  return (
    <ParentComponent counter={counter} setCounter={setCounter} />
  );
}

export default App;

ParentComponent.js

import React from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent({ counter, setCounter }) {
  return (
    <div>
      <h1>Parent Component</h1>
      <p>Counter in Parent: {counter}</p>
      <button onClick={() => setCounter(counter + 1)}>
        Increment in Parent
      </button>
      <ChildComponent counter={counter} setCounter={setCounter} />
    </div>
  );
}

export default ParentComponent;

ChildComponent.js

import React from 'react';

function ChildComponent({ counter, setCounter }) {
  return (
    <div>
      <h2>Child Component</h2>
      <p>Counter in Child: {counter}</p>
      <button onClick={() => setCounter(counter - 1)}>
        Decrement in Child
      </button>
    </div>
  );
}

export default ChildComponent;

Explanation

  • State is lifted to App: The counter state and setCounter function are declared in the App component.
  • Props are passed down: counter and setCounter are passed from App to ParentComponent, and then from ParentComponent to ChildComponent.
  • Both components share the state: ParentComponent and ChildComponent can both read and update the counter.

Prop Drilling

Prop drilling occurs when you pass props through intermediate components that do not need them, just to reach a component further down the tree.

In the Example:

  • ParentComponent receives counter and setCounter primarily to pass them to ChildComponent.
  • If ParentComponent doesn't need these props for its own functionality, it's merely a conduit, which is prop drilling.

Issues with Prop Drilling

  • Maintainability: As the app grows, passing props through many layers becomes hard to manage.
  • Readability: Intermediate components become cluttered with props they don't use.
  • Scalability: Adding or removing props requires changes at multiple levels.

Key Takeaways

  • Lifting State Up: Centralizes state management in a common ancestor to share state among components.
  • Prop Drilling: Passing props down through multiple nested components, which can become cumbersome and hard to maintain.

Summary

  • Components, props, and state are foundational concepts in React.
  • Managing state efficiently is key to building dynamic applications.
  • Reusability and composition make React powerful for front-end development.