Lesson 4 - Modern JavaScript (JSX) Patterns
Modern JavaScript Programming with React
Libraries vs Frameworks
Collection of reusable code
Predetermined architecture - you follow a specified pattern of development
Reduces need to write repetitive/complex things from scratch
You work within the boundaries set by the framework
You control how/when it's used. No/few boundaries.
"Right" and "wrong" ways to use it.
Similarities and Differences
Control
You call the library's functions.
The framework calls your code.
Structure
Focused on specific tasks/tools.
Provides a full application structure.
Scope
Smaller, solves specific problems.
Larger, provides a complete solution.
Flexibility
Very flexible, use what you need.
Less flexible, must follow its rules.
Learning Curve
Generally easier to learn.
Steeper learning curve.
Web Dev Use
UI components (React, jQuery UI), utilities (Lodash), date/time (Moment.js).
Single-page apps (Angular, Vue, React with routing/state management), complex UIs.
Key takeaway:
Libraries: Tools you use within your code.
Frameworks: Structures you build your code within.
History

Part One: Functions in Modern JavaScript
Lesson Objectives:
Function expression and Function Hoisting
How Closure Works
Understand anonymous functions and their usage.
Explore commonly used array methods (
map
,filter
,reduce
, etc.).Master arrow functions and their syntax.
Destructuring with JavaScript
Learn best practices for writing functions, especially in the React ecosystem.
Programming Activities for Part One
Preliminary Concepts
Function Expression
A function expression in JavaScript is a way to define a function as part of an expression.
// Assignment to a variable
const myFunc = function(x) { return x * 2; }; // Anonymous function expression
const multiply = function double(x) { return x * 2; }; // Named function expression
// As an argument to another function (callbacks)
const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) { return num * 2; }); // Function expression as callback
// An arrow function syntax (a concise form of function expression)
const square = (x) => x * x; // Arrow function expression
Function Hoisting
Function hoisting is a JavaScript behavior where function declarations are conceptually moved to the top of their scope before the code is executed.
// function hoisting
hoistedFunction(); // This works!
function hoistedFunction() {
console.log("This function is hoisted.");
}
// functionExpression(); // This would cause an error: "functionExpression is not defined"
const functionExpression = function() {
console.log("Function expressions are NOT hoisted.");
};
hoistedFunction(); // This also works.
Closure
A closure in JavaScript is a function that has access to variables from an enclosing (lexical) scope, even after the outer function has finished executing.
// closure
function outerFunction() {
const outerVar = "Hello from outer";
let count=0
function innerFunction() {
count++;
console.log(outerVar); // Accessing outerVar from the outer function
console.log(count); // Accessing innerVar from the inner function
}
return innerFunction; // Returning the inner function (the closure)
}
const myCount1 = outerFunction(); // myCount1 now holds the innerFunction
myCount1(); // Output: 1
myCount1(); // Output: 2
Advanced Closure Module Pattern with Data Privacy Encapsulation
The Advanced Closure Module Pattern enhances the classic module pattern by leveraging closures for robust data privacy and encapsulation.
// closure-advanced.js
const createDog = function (name) { // Outer function: takes the pet's initial name
let breed; // Private variable to store the pet's breed(initially undefined)
function setName(newName) { // Inner function: sets the pet's name
name = newName; // Modifies the 'name' variable in the outer function's scope (closure)
}
function getName() { // Inner function: gets the pet's name
return name; // Accesses the 'name' variable from the outer function's scope (closure)
}
function setBreed(newBreed) { // Inner function: sets the pet's breed
breed= newBreed; // Modifies the 'breed' variable in the outer function's scope (closure)
}
function getBreed() { // Inner function: gets the pet's sex
return breed; // Accesses the 'breed' variable from the outer function's scope (closure)
}
// This is the core of the module pattern. It returns a function.
return function (password) { // This inner function takes a password
if (password === "pets") { // Checks if the provided password is correct
return { // If the password is correct, it returns an object.
setName, // This object contains the inner functions, effectively making them public.
getName, // These functions have closure over 'name' and 'breed'.
setBreed,
getBreed,
};
} else {
return console.log("Error, incorrect password!"); // If the password is wrong, it logs an error.
}
};
};
// Usage:
// correct password
//const getAccessToFluffy = createDog("Fluffy"); // Create a "dog creator" for Fluffy. It does NOT give access yet.
//const fluffy = getAccessToFluffy("pets"); // Call the returned function with the correct password to get access.
const fluffy = createDog("Fluffy")("pets")
if (fluffy) { // Check to make sure we got access (password was correct)
console.log(fluffy.getName()); // "Fluffy"
fluffy.setName("Fluffball");
console.log(fluffy.getName()); // "Fluffball"
fluffy.setBreed("Poodle");
console.log(fluffy.getBreed()); // "Poodle"
}
//wrong password
const getAccessToRover = createDog("Rover");
const rover = getAccessToRover("wrongpassword"); // Incorrect password
if (!rover) {
console.log("No access to Rover because of wrong password")
}
Activity 1: Using Anonymous Functions
What are Anonymous Functions?
Functions without a name.
Often used as callbacks in JavaScript.
Hands-On Example:
Open your React project and modify a component as follows:
const AnonymousExample = () => { const numbers = [1, 2, 3, 4]; const squaredNumbers = numbers.map(function (num) { return num * num; }); return ( <div> <h3>Squared Numbers</h3> <p>{squaredNumbers.join(", ")}</p> </div> ); }; export default AnonymousExample;
Discuss:
Advantages: Concise and directly tied to their context.
Use cases: Callbacks for
map
,filter
, and event handlers in React.
Activity 2: Commonly Used Array Methods
Methods Covered:
map
,filter
,reduce
,find
,some
,every
, etc.
Task:
Create a
DataManipulation
component:import React from 'react'; function DataManipulation() { const products = [ { id: 1, name: 'Laptop', price: 1200, category: 'Electronics' }, { id: 2, name: 'Keyboard', price: 75, category: 'Electronics' }, { id: 3, name: 'Book', price: 25, category: 'Books' }, { id: 4, name: 'Mouse', price: 30, category: 'Electronics' }, { id: 5, name: 'Notebook', price: 10, category: 'Books' }, ]; // map: Transforms each element in the array const productNames = products.map((product) => product.name); const discountedPrices = products.map((product) => ({ ...product, price: product.price * 0.9 })); // 10% discount // filter: Creates a new array with elements that pass a condition const electronics = products.filter((product) => product.category === 'Electronics'); const expensiveProducts = products.filter((product) => product.price > 100); // reduce: Combines all elements into a single value const totalPrice = products.reduce((accumulator, product) => accumulator + product.price, 0); const productSummary = products.reduce((summary, product) => `${summary}${product.name} (${product.category}) - $${product.price}\n`, ""); // find: Returns the first element that satisfies a condition const bookCategory = products.find((product) => product.category === 'Books'); const productOver1000 = products.find((product) => product.price > 1000); // some: Checks if at least one element satisfies a condition const hasElectronics = products.some((product) => product.category === 'Electronics'); const hasCheapProduct = products.some((product) => product.price < 20); // every: Checks if all elements satisfy a condition const allElectronics = products.every((product) => product.category === 'Electronics'); const allProductsAffordable = products.every((product) => product.price < 2000); return ( <div> <h2>Data Manipulation Examples</h2> <p>Product Names: {JSON.stringify(productNames)}</p> <p>Discounted Prices: {JSON.stringify(discountedPrices)}</p> <p>Electronics: {JSON.stringify(electronics)}</p> <p>Expensive Products: {JSON.stringify(expensiveProducts)}</p> <p>Total Price: ${totalPrice}</p> <p>Product Summary: <pre>{productSummary}</pre></p> {/* Use <pre> for formatted text */} <p>Book Category: {JSON.stringify(bookCategory)}</p> <p>Product Over $1000: {JSON.stringify(productOver1000)}</p> <p>Has Electronics: {hasElectronics.toString()}</p> <p>Has Cheap Product: {hasCheapProduct.toString()}</p> <p>All Electronics: {allElectronics.toString()}</p> <p>All Products Affordable: {allProductsAffordable.toString()}</p> </div> ); } export default DataManipulation;
Explain:
How
filter
extracts specific items.How
map
transforms an array.How reduce combines elements
How find returns element
Activity 3: Arrow Functions
Syntax:
const add = (a, b) => a + b; const double = n => n * 2; // Single parameter doesn’t require parentheses
React Integration:
Update the
ArrowExample
from earlier to use arrow functions:const ArrowExample = () => { const numbers = [1, 2, 3, 4]; const squaredNumbers = numbers.map(num => num * num); return ( <div> <h3>Squared Numbers</h3> <p>{squaredNumbers.join(", ")}</p> </div> ); }; export default ArrowExample;
Best Practices:
Use arrow functions for short functions and callbacks.
Avoid them in event handlers when
this
is required.
Part Two: Asynchronous Programming
Lesson Objectives:
Understand and use callbacks.
Use promises effectively.
Refactor code using async/await.
Learn React-specific async programming practices.
Programming Activities for Part Two
Activity 1: Using Callbacks
Example:
const fetchData = (callback) => { setTimeout(() => { callback("Data fetched successfully"); }, 2000); }; const CallbackExample = () => { const buttonClick = () => { fetchData(message => { alert(message); }); }; return <button onClick={buttonClick}>Fetch Data</button>; }; export default CallbackExample;
Discuss:
How callbacks work.
Issues: Callback hell.
Activity 2: Promises (better Solution to Callback hell)
Task:
Refactor the callback code using promises:
const fetchData = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("Data fetched successfully"); }, 2000); }); }; const PromiseExample = () => { const buttonClick = () => { fetchData().then(message => { alert(message); }); }; return <button onClick={buttonClick}>Fetch Data</button>; }; export default PromiseExample;
Explain:
How promises handle asynchronous tasks.
Benefits over callbacks.
Activity 3: Async/Await
Refactor the Promises Example:
const fetchData = async () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("Data fetched successfully"); }, 2000); }); }; const AsyncAwaitExample = () => { const buttonClick = async () => { const message = await fetchData(); alert(message); }; return <button onClick={buttonClick}>Fetch Data</button>; }; export default AsyncAwaitExample;
Benefits of Async/Await:
Cleaner syntax.
Avoids promise chaining.
Activity 4: Destructuring Assignment
The destructuring assignment syntax is an expression that makes it possible to unpack values from arrays or properties from objects. It's a very common and useful feature in modern JavaScript.
// Array destructuring:
const numbers = [1, 2, 3];
// Traditional way:
const first = numbers[0]; // first = 1
const second = numbers[1]; // second = 2
const third = numbers[2]; // third = 3
// With destructuring:
const [a, b, c] = numbers; // a = 1, b = 2, c = 3
// Skipping elements:
const [, , d] = numbers; // d = 3 (skips the first two elements)
// Rest operator with ... (spread) operator:
const [e, ...rest] = numbers; // e = 1, rest = [2, 3]
// Object destructuring:
const person = {
name: "Alice",
age: 30,
city: "New York"
};
// Traditional way:
const personName = person.name; // personName = "Alice"
const personAge = person.age; // personAge = 30
// With destructuring:
const { name, age, city } = person; // name = "Alice", age = 30, city = "New York"
// Renaming properties:
const { name: userName, age: userAge } = person; // userName = "Alice", userAge = 30
// Default values:
const { country = "USA" } = person; // country = "USA" (since 'country' is not in the object)
// Nested object destructuring:
const student = {
info: {
name: "Bob",
age: 20
}
};
const { info: { name: studentName } } = student; // studentName = "Bob"
// Combined array and object destructuring:
const data = [
{ id: 1, name: "Product A" },
{ id: 2, name: "Product B" }
];
const [{ name: productName1 }, { name: productName2 }] = data; // productName1 = "Product A", productName2 = "Product B"
console.log(a, b, c);
console.log(d);
console.log(e, rest);
console.log(name, age, city);
console.log(userName, userAge);
console.log(country);
console.log(studentName);
console.log(productName1, productName2);
Anatomy of main.jsx
open Chrome Developer Tools (by CTRL+SHIFT+I (or F12 key) and open Console to explore console log output.
Console › {type: 'h1', key: null, props: {children: 'Hello from createElement!'}, _owner: null, _store: {}}
// main.jsx
import { createElement } from "react"
import { createRoot } from "react-dom/client"
//import ReactDom from 'react-dom/client'
const root = createRoot(document.getElementById("root"))
const reactElement = createElement("h1", null, "Hello from createElement!")
console.log(reactElement)
root.render(
reactElement
)
Key Takeaways for Students
Modern JavaScript features, such as arrow functions, anonymous functions, and array methods, are essential for writing React components effectively.
Master asynchronous programming techniques, as React often involves handling async tasks (e.g., API calls).
Refactor code for clarity and maintainability, using async/await when possible.
Why React?
Lego Bricks Block Build


Vanilla JavaScrpt vs React
// index.html
<html>
<body>
<div id="app">
<script type="text/javascript">
const app = document.getElementById('app');
// creates a new h1 element
const header = document.createElement('h1');
// create a new text node for the h1 element
const headerContent = document.createTextNode(
'This is my web application!');
// append the text to the h1 element
header.appendChild(headerContent);
// place the h1 element inside the div
app.appendChild(header);
</script>
</div>
</body>
</html>
React's popularity stems from a combination of factors that make it a compelling choice for web development:
Component-Based Architecture: This promotes code reusability, organization, and maintainability, especially in large applications.
Virtual DOM: This enhances performance by minimizing direct manipulations to the actual DOM, leading to faster rendering and smoother user experiences.
Large and Active Community: This provides ample resources, libraries, and support for developers.
JSX: This syntax extension allows developers to write HTML-like code within JavaScript, making UI development more intuitive. It allows to create easily reusable and interchangeable "pieces of of the web" that can be combined in various ways to create complex systems
Strong Focus on UI: React excels at building interactive and dynamic user interfaces.
Declarative Programming : Focuses on what the program should do, and describes the desired outcome without specifying how to achieve it.
In short, React offers a powerful, efficient, and developer-friendly way to build modern web applications.
Last updated