JavaScript Fundamentals for React: A Comprehensive Guide

JavaScript Fundamentals for React

Master JavaScript fundamentals for React development. Learn key concepts like variables, functions, classes, and ES6+ features with examples. Before diving deep into React components, hooks, or state management, you must have a solid understanding of JavaScript fundamentals. React is built on JavaScript — not a separate language, but a library that uses modern JavaScript features extensively.

Whether you’re a PHP developer shifting to React, a WordPress developer learning modern front-end, or a beginner starting your React journey, this guide will help you understand the core JavaScript concepts used in React development with definitions, examples, and summaries.


Variables and Scope

Variables in JavaScript store data values and are one of the JavaScript Fundamentals for React. React uses variables to manage dynamic UI states, props, and configuration values.

JavaScript provides three ways to declare variables: var, let, and const. Each has distinct characteristics regarding scope, hoisting behavior, and reassignment rules.​

var is the original keyword for declaring variables in JavaScript. It is function-scoped or globally scoped, depending on where it’s declared. Variables declared with var can be updated and re-declared within the same scope.​

let declares variables with block scope, allowing updates but not re-declaration within the same block. This makes it more predictable and less prone to bugs compared to var.​

const declares block-scoped variables that cannot be reassigned after their initial assignment. However, for objects and arrays, the properties or elements can still be modified.

Types

  • var — function-scoped
  • let — block-scoped
  • const — block-scoped and constant

Example

// var - function scoped
function testVar() {
if (true) {
var x = 10;
}
console.log(x); // 10 - accessible outside block
}

// let - block scoped
function testLet() {
if (true) {
let y = 20;
}
// console.log(y); // ReferenceError: y is not defined
}

// const - block scoped and immutable binding
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable

// const with objects - properties can be modified
const user = { name: 'John', age: 30 };
user.age = 31; // This works
console.log(user); // { name: 'John', age: 31 }

Use const by default for variables that won’t be reassigned. Use let when you know a variable’s value might change later in your code. Avoid var in modern JavaScript to prevent scoping issues.​

In React, you’ll commonly see const used for component declarations and state variables that receive new references rather than being reassigned:

const [count, setCount] = useState(0);
const users = [{ name: 'Robin' }, { name: 'Markus' }];

Use let and const instead of var for better block-scoping and more predictable behavior in React components.


Arrow Functions

Functions are reusable blocks of code and are one of the JavaScript fundamentals for React. In React, they are used to create functional components, handle events, and manipulate data.

Arrow functions provide a concise syntax for writing functions in JavaScript, and are one of the JavaScript Fundamentals for React. They were introduced in ES6 and offer several advantages, particularly in React development

Key Features

Arrow functions do not create their own this context. Instead, they inherit the this value from the enclosing scope, which can be helpful in callback functions and event handlers.​

For single expressions, arrow functions can use implicit return without the return keyword and curly braces:

Example

// Traditional function
function add(a, b) {
return a + b;
}

// Arrow function with explicit return
const add = (a, b) => {
return a + b;
};

// Arrow function with implicit return
const add = (a, b) => a + b;

// Single parameter - parentheses optional
const square = num => num * num;

Example: Arrow Functions in React

import React from 'react';
// React component using arrow function
const MyComponent = () => {
const handleClick = () => {
console.log('Button clicked');
};
return (
<button onClick={handleClick}>
Click me
</button>
);
};
export default MyComponent;

Summary

Arrow functions make code concise and preserve the this context — important when handling events in React (e.g., onClick handlers).

Arrow functions simplify React component definitions and event handlers. They eliminate the need for manual function binding in class components because they automatically inherit the parent scope’s this context. This makes your code more concise and eliminates common bugs related to this binding.


Objects Destructuring

Objects group related data and functions. Destructuring is a JavaScript expression and one of JavaScript Fundamentals for React that allows you to extract values from objects or arrays into distinct variables. This feature is extensively used in React for handling props and state.

Example

// Without destructuring
const user = {
name: 'John',
age: 30,
city: 'New York'
};

const name = user.name;
const age = user.age;
const city = user.city;

// With destructuring
const { name, age, city } = user;
console.log(name); // John
console.log(age); // 30

// Renaming variables
const { name: userName, age: userAge } = user;
console.log(userName); // John

// Default values
const { country = 'USA' } = user;
console.log(country); // USA

Array Destructuring

const numbers = [1, 2, 3, 4, 5];

// Destructuring arrays
const [first, second, ...rest] = numbers;
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]

// Skipping elements
const [, , third] = numbers;
console.log(third); // 3

Example: Destructuring in React

import React, { useState } from 'react';

// Props destructuring in function parameters
function Greeting({ name, age }) {
return <h1>Hello, {name}! You are {age} years old.</h1>;
}

// Destructuring in component body
function UserCard(props) {
const { name, email, avatar } = props;

return (
<div>
<img src={avatar} alt={name} />
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}

// Destructuring useState
function Counter() {
const [count, setCount] = useState(0);

return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}

Summary

Destructuring makes your React code cleaner and more readable. It’s particularly useful for extracting props, state values, and hook returns. React developers use destructuring extensively to avoid repetitive props.propertyName syntax and to work with the values returned by hooks like useState.


Template Literals

Template literals (also called template strings) are string literals that allow embedded expressions, multi-line strings, and string interpolation. They use backticks (`) instead of quotes.

Example

// Traditional string concatenation
const name = 'John';
const age = 30;
const greeting = 'Hello, my name is ' + name + ' and I am ' + age + ' years old.';

// Template literal
const greeting = `Hello, my name is ${name} and I am ${age} years old.`;

// Multi-line strings
const message = `
This is a multi-line
string that spans
multiple lines.
`;

// Expression evaluation
const a = 10;
const b = 20;
const result = `The sum of ${a} and ${b} is ${a + b}.`;
console.log(result); // The sum of 10 and 20 is 30.

Example: Template Literals in React

import React from 'react';

function UserProfile({ user }) {
return (
<div>
<h1>{`Welcome, ${user.firstName} ${user.lastName}!`}</h1>
<p>{`You have ${user.notifications} new notifications.`}</p>
</div>
);
}

export default UserProfile;

Summary

Template literals make string construction cleaner and more readable. In React, they’re particularly useful for creating dynamic class names, constructing URLs, and formatting text. They eliminate the need for cumbersome string concatenation and make your code more maintainable.


Classes and this Keyword

Classes are templates for creating objects and one of the JavaScript Fundamentals for React. React class components extend from React.Component.

Example

class Person {
constructor(name) {
this.name = name;
}greet() {
console.log(`Hi, I'm ${this.name}`);
}
}const user = new Person("Umang");
user.greet();

Summary

Although React now prefers functional components, understanding classes is essential for maintaining legacy React apps.


Spread and Rest Operators

The Spread Operator

The spread operator (...) helps you expand iterables into individual elements. It’s effective within array literals, function calls, and property objects.​

Example: Spread Operator

// Spreading arrays
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

// Spreading objects
const person = { name: 'John', age: 30 };
const newPerson = { ...person, city: 'New York' };
console.log(newPerson); // { name: 'John', age: 30, city: 'New York' }

// Combining objects
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const combined = { ...obj1, ...obj2 };
console.log(combined); // { a: 1, b: 2, c: 3, d: 4 }

The Rest Operator

The rest operator (...) collects the remaining elements of an array or object into a new array or object.​

// Rest in arrays
const numbers = [1, 2, 3, 4, 5];
const [first, ...rest] = numbers;
console.log(rest); // [2, 3, 4, 5]

// Rest in objects
const user = { name: 'John', age: 30, city: 'New York', country: 'USA' };
const { name, ...otherDetails } = user;
console.log(otherDetails); // { age: 30, city: 'New York', country: 'USA' }

// Rest parameters in functions
function sum(...numbers) {
  return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

Example: Spread/Rest in React

import React, { useState } from 'react';

// Passing props with spread operator
function MyButton() {
  const props = { 
    type: 'button', 
    className: 'btn-primary', 
    disabled: false 
  };
  return <button {...props}>Click Me</button>;
}

// Rest operator with props
function Modal({ onClick, ...rest }) {
  return (
    <div {...rest}>
      <button onClick={onClick}>Close</button>
    </div>
  );
}

// Updating state immutably with spread
function UserProfile() {
  const [user, setUser] = useState({
    name: 'Alice',
    preferences: { theme: 'light', notifications: true }
  });
  
  function updatePreferences(newPreferences) {
    setUser({
      ...user,
      preferences: { ...user.preferences, ...newPreferences }
    });
  }
  
  return (
    <button onClick={() => updatePreferences({ theme: 'dark' })}>
      Toggle Theme
    </button>
  );
}

Summary

The spread operator is essential for React development because it allows you to create copies of arrays and objects without mutating the originals. This is crucial for maintaining immutability in React state updates. The rest operator helps you collect remaining props and pass them down to child components efficiently.


Array Methods: map(), filter(), and reduce()

The map() Method

The map() method creates a new array by applying a function to each element of the original array. It’s one of the most frequently used array methods in React.​

Syntax:

arr.map((element, index, array) => {
  // return transformed element
});

Example: map() in JavaScript

const numbers = [1, 2, 3, 4, 5];

// Multiply each number by 2
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// Transform objects
const users = [
  { firstName: 'John', lastName: 'Doe' },
  { firstName: 'Jane', lastName: 'Smith' }
];

const fullNames = users.map(user => `${user.firstName} ${user.lastName}`);
console.log(fullNames); // ['John Doe', 'Jane Smith']

Example: map() in React

import React from 'react';
function UserList() {
  const users = [
    { id: 1, name: 'Robin' },
    { id: 2, name: 'Markus' }
  ];
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

The filter() Method

The filter() method creates a new array containing only elements that pass a test implemented by a provided function.​

Example: filter() in JavaScript

const numbers = [1, 2, 3, 4, 5, 6, 7, 8];

// Get numbers greater than 5
const filtered = numbers.filter(num => num > 5);
console.log(filtered); // [6, 7, 8]

// Filter objects
const users = [
  { name: 'John', age: 25 },
  { name: 'Jane', age: 30 },
  { name: 'Bob', age: 20 }
];

const adults = users.filter(user => user.age >= 25);
console.log(adults); // [{ name: 'John', age: 25 }, { name: 'Jane', age: 30 }]

Example: filter() in React

import React, { useState } from 'react';

function SearchableList() {
  const [query, setQuery] = useState('');
  const users = [
    { id: 1, name: 'Robin' },
    { id: 2, name: 'Markus' },
    { id: 3, name: 'Robert' }
  ];
  
  return (
    <div>
      <input 
        type="text" 
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search users..."
      />
      <ul>
        {users
          .filter(user => user.name.toLowerCase().includes(query.toLowerCase()))
          .map(user => (
            <li key={user.id}>{user.name}</li>
          ))
        }
      </ul>
    </div>
  );
}

The reduce() Method

The reduce() method applies a function to an accumulator and each array element to reduce it to a single value.​

Syntax:

arr.reduce((accumulator, currentValue, index, array) => {
  // return updated accumulator
}, initialValue);

Example: reduce() in JavaScript

const numbers = [1, 2, 3, 4, 5];

// Sum all numbers
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15

// Count occurrences
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});
console.log(count); // { apple: 3, banana: 2, orange: 1 }

Example: Combining map(), filter(), and reduce()

const data = [1, 2, 3, 4, 5, 6, 7, 8];

const result = data
  .map(item => item * 2)        // [2, 4, 6, 8, 10, 12, 14, 16]
  .filter(item => item > 10)    // [12, 14, 16]
  .reduce((acc, item) => acc + item, 0); // 42

console.log(result); // 42

Example: reduce() in React

import React from 'react';

function SuperHeroStats() {
  const heroes = [
    { id: 101, name: 'Ironman', strength: 1000 },
    { id: 102, name: 'Thor', strength: 10000 },
    { id: 103, name: 'Hulk', strength: 15000 }
  ];
  
  const totalStrength = heroes.reduce(
    (acc, hero) => acc + hero.strength, 
    0
  );
  
  return (
    <div>
      <h2>Combined Strength: {totalStrength}</h2>
      <ul>
        {heroes
          .filter(hero => hero.strength > 800)
          .map(hero => (
            <li key={hero.id}>
              {hero.name}: {hero.strength}
            </li>
          ))
        }
      </ul>
    </div>
  );
}

Summary

These three array methods are fundamental to React development. The map() method is essential for rendering lists of components, filter() helps implement search and filtering functionality, and reduce() is useful for computing derived values from arrays. Understanding these methods eliminates the need for traditional loops and makes your code more functional and declarative.​


Modules: Import and Export

ES6 Module System

JavaScript’s ES6 module system allows you to organize code into separate files and share functionality between them. React applications heavily rely on this module system for component organization.​

Default Export and Import

A file can have one default export.​

// MyComponent.js
import React from 'react';

const MyComponent = () => {
  return <h1>Hello from MyComponent!</h1>;
};

export default MyComponent;

// App.js
import MyComponent from './MyComponent';

function App() {
  return (
    <div>
      <MyComponent />
    </div>
  );
}

export default App;

Named Export and Import

Multiple named exports can exist in a single file.​

// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;// App.js
import { add, subtract, multiply } from './utils';console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
console.log(multiply(5, 3)); // 15

Combining Default and Named Exports

// components.js

import React from 'react';export const Header = () => <h1>Welcome to My Website</h1>;

export const Footer = () => <footer>© 2023 My Website</footer>;export default function MainContent() {

return <div>This is the main content.</div>;

}

// App.js
import MainContent, { Header, Footer } from './components';

function App() {
return (
<div>
<Header />
<MainContent />
<Footer />
</div>
);
}

Import All

// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;// App.js
import * as MathUtils from './utils';console.log(MathUtils.add(5, 3)); // 8
console.log(MathUtils.subtract(5, 3)); // 2

Summary

The import/export syntax is JavaScript Fundamentals for React. It allows you to create modular, reusable components and utilities. Use default exports for primary components and named exports for utility functions or when exporting multiple items from a single file.​


Promises and Async/Await

Understanding Promises

Promises provide a more convenient API to handle asynchronous operations. They represent the eventual success or failure of an asynchronous operation.​

A Promise can be in one of three states:​

  • Pending: Initial state, neither fulfilled nor rejected

  • Fulfilled: Operation completed successfully

  • Rejected: Operation failed

Example: Basic Promise

// Creating a Promise
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => {
const data = { user: 'John', age: 30 };
resolve(data); // Success
// reject('Error occurred'); // Failure
}, 1000);
});// Using a Promise
fetchData
.then(data => {
console.log('Data received:', data);
})
.catch(error => {
console.error('Error:', error);
});

Async/Await

The async/await syntax provides a cleaner way to work with promises. The async keyword declares an asynchronous function that returns a promise. The await keyword makes JavaScript wait until a promise settles and returns its result.​

Example: Async/Await Syntax

// Traditional promise chaining
function fetchUserData() {
fetch('https://api.example.com/user')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
}// Using async/await
async function fetchUserData() {
try {
const response = await fetch('https://api.example.com/user');
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}

Example: Async/Await in React

import React, { useState, useEffect } from 'react';

function UserComponent() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const fetchUser = async () => {
try {
const response = await fetch('https://api.example.com/user');

if (!response.ok) {
throw new Error('Failed to fetch user');
}

const data = await response.json();
setUser(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

fetchUser();
}, []);

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return null;

return (
<div>
<h1>{user.name}</h1>
<p>Email: {user.email}</p>
</div>
);
}

export default UserComponent;

Promise Methods

Understanding these Promise methods is helpful for React development:​

// Promise.all - Wait for all promises

const fetchMultipleResources = async () => {

const [users, posts, comments] = await Promise.all([

fetch('/api/users').then(res => res.json()),

fetch('/api/posts').then(res => res.json()),

fetch('/api/comments').then(res => res.json())

]);return { users, posts, comments };

};// Promise.race - Return first settled promise

const fetchWithTimeout = async () => {

const timeout = new Promise((_, reject) =>

setTimeout(() => reject(new Error('Timeout')), 5000)

);const data = await Promise.race([

fetch('/api/data').then(res => res.json()),

timeout

]);

return data;
};

Summary

Promises and async/await are one of the JavaScript Fundamentals for React and essential for handling asynchronous operations in React, such as API calls, file operations, and timers. The async/await syntax makes asynchronous code more readable and easier to maintain. In React, you’ll frequently use these patterns within useEffect hooks to fetch data when components mount or when dependencies change.​


Closures

A closure is a function that retains access to its outer function’s variables, even after the outer function has finished executing. Closures are JavaScript fundamentals for React and appear frequently in React code.​

Example: Basic Closure

function start() {

const firstName = 'John';// displayFirstName creates a closure

function displayFirstName() {

console.log(firstName); // Accesses outer variable

}displayFirstName(); // Prints "John"

}start();

// Counter with closure
function createCounter() {
let count = 0;

return function() {
count++;
return count;
};
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Example: Closures in React

import React, { useCallback, useEffect } from 'react';

// Every function in React component is a closure
const Component = () => {
const onClick = () => {
// This is a closure
console.log('Button clicked');
};

return <button onClick={onClick}>Click Me</button>;
};

// Closures in useEffect
function TimerComponent() {
const [count, setCount] = React.useState(0);

useEffect(() => {
// This closure captures the current count value
const timer = setInterval(() => {
console.log(`Count is: ${count}`);
}, 1000);

return () => clearInterval(timer);
}, [count]); // Dependencies matter for closures

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

// Stale closures - common React issue
function StaleClosureExample() {
const [value, setValue] = React.useState('');

const handleSubmit = useCallback(() => {
// This closure captures the initial value
// It won't update unless dependencies change
console.log(value);
}, []); // Empty deps - closure is stale

const handleSubmitCorrect = useCallback(() => {
// This closure updates when value changes
console.log(value);
}, [value]); // Correct dependencies

return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}

Summary

Closures are everywhere in React components, and one of the JavaScript Fundamentals for React. Every function defined inside a component is a closure that has access to the component’s props, state, and other variables. Understanding closures helps you avoid common React bugs, particularly “stale closures” where callbacks capture outdated values. This is why dependency arrays in hooks like useEffect and useCallback are so important.​


DOM vs Virtual DOM

  • DOM (Document Object Model) represents the web page.

  • Virtual DOM is React’s lightweight copy that efficiently updates changes.

Example Summary

In vanilla JS:

document.getElementById("root").innerHTML = "Hello";

In React:

function App() {
return <h1>Hello</h1>;
}

React updates the Virtual DOM first, then synchronizes changes to the real DOM — improving performance.


Event Handling and Callbacks

Definition

Events like clicks, inputs, or key presses are handled using functions and one of the JavaScript Fundamentals for React. React uses camelCase event names and passes functions as event handlers.

Example

function Button() {
const handleClick = () => alert("Button clicked!");
return <button onClick={handleClick}>Click Me</button>;
}

Summary

Understanding how to handle events using callback functions is key to building interactive React apps.


References

  1. MDN Web Docs – JavaScript Guide

  2. React Official Documentation

  3. JavaScript.info

  4. W3Schools JavaScript Tutorial


Conclusion

Learning React without strong JavaScript fundamentals for React is like building a house on sand. Mastering variables, functions, objects, ES6 syntax, async programming, and modular code organization forms the bedrock for becoming a proficient React developer.

Once you’re comfortable with these concepts:

  • Start writing simple components.

  • Work with useState and useEffect hooks.

  • Build small projects (like Todo or Weather apps).

Every React feature — from JSX to Hooks — is powered by JavaScript. Strengthen these fundamentals, and React will feel natural to you.

Write a Reply or Comment

Your email address will not be published. Required fields are marked *