Himanshu SharmaSoftware engineer
Let’s talk

React · Lesson 2 of 38

The JavaScript you need for React

Review the modern JavaScript that React code uses every day: const and let, arrow functions, template literals, destructuring, spread, map, filter and modules.

18 minGetting startedUpdated 24 October 2026

By the end of this lessonRead and write the JavaScript patterns that appear in almost every React component without stumbling over the syntax.

You do not need to be a JavaScript expert to start React, but you do need to read a handful of modern features without blinking. Almost every React component uses them. This lesson reviews exactly those. If any part is new, run the examples and change them; each takes a minute. The editors run React code, so values are shown on the page with a tiny component: that is already the pattern you will use all course.

const and let

Declare variables with const when they will not be reassigned, and let when they will. Avoid the old var. In React code you will write const most of the time.

jsx
function App() {
  const price = 200;        // cannot be reassigned
  let quantity = 2;         // can be reassigned
  quantity = quantity + 1;
  const total = price * quantity;

  const user = { name: "Asha" };
  user.name = "Ravi";       // allowed: const stops reassignment, not changes inside the object

  return <p>{quantity} items, total {total}, user {user.name}</p>;
}
export default App;
result
3 items, total 600, user Ravi

const does not make an object or array unchangeable: it only stops you pointing the name at something else. React nevertheless asks you to treat data as read-only, and later lessons show how to update objects and arrays by making copies.

Functions and arrow functions

A function can be written in two common ways. The arrow form is shorter and is used everywhere in React for small functions, especially callbacks:

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

const addArrow = (a, b) => a + b;        // one expression: the value is returned automatically
const square = n => n * n;               // one parameter: brackets are optional
const greet = name => {                  // a block body needs an explicit return
  const message = "Hello, " + name;
  return message;
};

function App() {
  return <p>{add(2, 3)} {addArrow(4, 5)} {square(6)} {greet("Asha")}</p>;
}
export default App;
result
5 9 36 Hello, Asha

Two details trip beginners. When an arrow function returns an object literal, wrap it in brackets: () => ({ a: 1 }), because curly braces alone start a function body. And functions can be passed around like any value, which is how event handlers and map callbacks work.

Template literals

Backticks create strings that can contain expressions and span lines. You will use them for class names, messages and URLs.

jsx
function App() {
  const name = "Asha";
  const items = 3;
  const message = `Hello ${name}, you have ${items} item${items === 1 ? "" : "s"}.`;
  return <p>{message}</p>;
}
export default App;
result
Hello Asha, you have 3 items.

Objects and arrays

Objects hold named values, arrays hold ordered lists. Their items can be anything, including other objects and arrays: a list of users is an array of objects. Access with dot or bracket notation:

jsx
const users = [
  { id: 1, name: "Asha", skills: ["HTML", "CSS"] },
  { id: 2, name: "Ravi", skills: ["PHP"] },
];

function App() {
  const first = users[0];
  return (
    <p>
      {first.name} knows {first.skills.length} things; the last is {first.skills[first.skills.length - 1]}.
      There are {users.length} users.
    </p>
  );
}
export default App;
result
Asha knows 2 things; the last is CSS. There are 2 users.

Destructuring

Destructuring unpacks values from objects and arrays into variables. React uses it constantly, for example to read props and to receive the pair that useState returns.

jsx
function App() {
  const user = { name: "Asha", age: 30, city: "Pune" };
  const { name, city } = user;                 // object: matched by property name
  const { age: years } = user;                 // rename while unpacking
  const [first, second, ...rest] = [10, 20, 30, 40];   // array: matched by position

  return <p>{name} from {city}, {years} years. {first} {second} then {rest.join(",")}</p>;
}
export default App;
result
Asha from Pune, 30 years. 10 20 then 30,40

You can destructure in a function's parameter list too: function Greeting({ name, city }) takes an object and pulls out two properties. That is exactly what a React component does with its props.

The spread operator

... copies the items of an array or the properties of an object into a new one. It is the main tool for "changing" data without modifying the original:

jsx
function App() {
  const original = { name: "Asha", city: "Pune" };
  const moved = { ...original, city: "Delhi" };       // copy, then override one property
  const list = [1, 2, 3];
  const longer = [...list, 4];                         // copy and add at the end
  const merged = [0, ...list, ...[8, 9]];

  return (
    <p>
      original city: {original.city}; copy city: {moved.city}; list: {list.join(",")};
      longer: {longer.join(",")}; merged: {merged.join(",")}
    </p>
  );
}
export default App;
result
original city: Pune; copy city: Delhi; list: 1,2,3; longer: 1,2,3,4; merged: 0,1,2,3,8,9

The original objects stayed unchanged. Remember this pattern: to update something in React, make a new copy with the change. The lessons on state build on it.

map, filter and reduce

These array methods transform data without changing the original array. They are how React turns a list of data into a list of elements.

jsx
function App() {
  const prices = [120, 80, 45, 200];
  const doubled = prices.map(p => p * 2);                 // one result per item
  const cheap = prices.filter(p => p < 100);              // keep items that pass a test
  const total = prices.reduce((sum, p) => sum + p, 0);    // combine into one value
  const first = prices.find(p => p > 100);                // first match, or undefined
  const any = prices.some(p => p > 150);                  // is there at least one?

  return (
    <ul>
      <li>doubled: {doubled.join(", ")}</li>
      <li>cheap: {cheap.join(", ")}</li>
      <li>total: {total}</li>
      <li>first over 100: {first}</li>
      <li>any over 150: {String(any)}</li>
      <li>original unchanged: {prices.join(", ")}</li>
    </ul>
  );
}
export default App;
result
doubled: 240, 160, 90, 400
cheap: 80, 45
total: 445
first over 100: 120
any over 150: true
original unchanged: 120, 80, 45, 200

Prefer these over for loops in React code. map in particular is the engine behind rendering lists.

Optional chaining and nullish coalescing

Real data is often missing. ?. stops safely instead of throwing an error when something is null or undefined, and ?? supplies a default only for null or undefined (unlike ||, which also replaces 0 and the empty string).

jsx
function App() {
  const user = { profile: null, visits: 0 };
  const city = user.profile?.city;            // undefined, no error
  const shown = user.profile?.city ?? "unknown";
  const visits = user.visits ?? 10;           // keeps 0
  const wrong = user.visits || 10;            // replaces 0 with 10

  return <p>{String(city)} / {shown} / {visits} / {wrong}</p>;
}
export default App;
result
undefined / unknown / 0 / 10

Logical && and the ternary

Because JSX is an expression, you will use condition && value and condition ? a : b to decide what to show:

jsx
function App() {
  const loggedIn = true;
  const count = 0;
  return (
    <div>
      <p>{loggedIn ? "Welcome back" : "Please sign in"}</p>
      <p>{loggedIn && "You are signed in"}</p>
      <p>Messages: {count && "unread"}</p>
    </div>
  );
}
export default App;
result
Welcome back
You are signed in
Messages: 0

Look at the last line: 0 && "unread" evaluates to 0, and React renders the number 0. This surprises everyone once. Use count > 0 && ... so the left side is a real boolean.

Modules: import and export

Real projects split code into files. Each file is a module. A file shares things with export and another file uses them with import:

javascript
// math.js
export const PI = 3.14159;                 // named export
export function double(n) { return n * 2; }
export default function add(a, b) { return a + b; }   // one default export per file

// app.js
import add, { PI, double } from "./math.js";   // default first (any name), then named in braces
import { double as twice } from "./math.js";   // rename with "as"
import * as math from "./math.js";             // everything as one object

React components follow the same rule: a component file normally has one export default for the main component. Local files need a path starting with ./ or ../; packages like React are imported by name: import { useState } from "react";. The live editor lets you write import lines for React only, because it has just one file.

Promises and async/await

Fetching data takes time, so browser functions like fetch return a promise: a value that will arrive later. async/await lets you write the waiting code in a straight line:

javascript
async function loadUser() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
  const user = await response.json();
  return user.name;
}
loadUser().then(name => console.log(name));

You will use this in the lesson on fetching data. For now, remember that await can only be used inside an async function and that errors are caught with try/catch.

Common mistakes

  • Using var or reassigning const variables, which causes errors or confusing scope.
  • Forgetting the brackets when an arrow function returns an object literal.
  • Using || for defaults when 0 or "" are valid values; use ??.
  • Changing an array or object in place (push, assigning a property) when you should make a copy.
  • Importing a default export with braces, or a named export without them.
  • Writing {list.length && <List />}, which renders 0 for an empty list.

Exercise

  1. In the destructuring example, add a country property to user, unpack it, and show it in the paragraph.
  2. In the map and filter example, add a Math.max(...prices) line to show the largest price (spread into a function call).
  3. Make moved also change name, keeping original intact.
  4. Write a ternary that shows "item" or "items" depending on a count constant, and test it with 1 and 2.

Key points

  • Use const by default and let when a variable must be reassigned; avoid var.
  • Arrow functions, template literals, destructuring and the spread operator appear in nearly every React component.
  • map, filter and reduce turn arrays into new arrays and values without changing the original, which is exactly how React wants you to handle data.
  • import and export split code into files; a file can have one default export and many named exports.

Check yourself

1. What does const mean in JavaScript?
2. What is the result of [1, 2, 3].map(n => n * 2)?
3. What does const { name } = user do?
4. How do you import a named export called Button from ./Button.jsx?