# ✨ ES6 thiết yếu cho React: let, const, arrow function, destructuring, spread

By Better Wise

Đây là bài mở đầu của khóa. React được viết bằng JavaScript hiện đại (ES6+), nên gần như mọi dòng code React bạn gặp sau này đều dựa trên 5 thứ trong bài này: `let`/`const`, arrow function, template literal, destructuring và spread. Bạn đã biết HTML/CSS cơ bản rồi, nên ta chỉ cần thêm đúng phần JavaScript này là đủ để đọc và viết component.

Sau bài này, bạn sẽ:

- Phân biệt `let` và `const`, biết chọn cái nào theo mặc định
- Viết arrow function và tránh bẫy `this` cũng như bẫy trả về object
- Dùng template literal thay cho nối chuỗi bằng dấu `+`
- Bóc dữ liệu bằng destructuring object và array
- Dùng spread để tạo bản sao thay vì sửa trực tiếp dữ liệu gốc

## let và const: mặc định là const, chỉ đổi khi thật cần

Hãy nghĩ tới hai chiếc hộp dán nhãn. `const` là hộp dán băng keo: nhãn không đổi được. `let` là hộp dán nhãn bằng keo giấy: đổi nhãn lúc nào cũng được. Còn `var` là chiếc hộp cũ rò rỉ ra ngoài mọi ngăn kéo, ta bỏ hẳn.

```js
const tenApp = "Quản lý chi tiêu";
// tenApp = "Khác"; // TypeError: Assignment to constant variable

let soDu = 0;
soDu = 500000; // OK
```

Điểm quan trọng nhất, và cũng là chỗ người mới hiểu sai nhiều nhất:

```js
const user = { ten: "Lan", tuoi: 20 };
user.tuoi = 21;      // OK! const không đóng băng nội dung object
// user = {};        // Lỗi: gán lại biến thì không được
```

| Khai báo | Gán lại biến | Phạm vi | Dùng khi nào |
| --- | --- | --- | --- |
| `var` | được | hàm | tránh trong code mới |
| `let` | được | block | biến đếm, biến cộng dồn, giá trị thật sự thay đổi |
| `const` | không | block | mặc định cho hầu hết khai báo |

```mermaid
flowchart TD
    Start["Cần khai báo biến"] --> Q{"Giá trị có bị gán lại?"}
    Q -->|"Không"| Const["📌<br/>const"]
    Q -->|"Có"| Let["🔄<br/>let"]
```

**Bài tập 1.** Trong dự án quản lý chi tiêu, bạn cần một biến cộng dồn tổng tiền khi duyệt mảng các khoản chi. Dùng `let` hay `const`? Vì sao?

**Xem gợi ý**

Dùng `let tong = 0;` rồi `tong += khoan.tien;` trong vòng lặp, vì biến này bị gán lại nhiều lần. Mảng `khoanChi` thì dùng `const`.

## Arrow function: ngắn hơn, và `this` không bị đổi

```js
// Cách cũ
const chaoCu = function (ten) {
  return "Xin chào " + ten;
};

// Arrow function
const chao = (ten) => `Xin chào ${ten}`;
```

Ba quy tắc viết gọn:

- Một tham số thì bỏ được ngoặc: `x => x * 2`
- Thân hàm chỉ có một biểu thức thì bỏ được `return` và `{}`
- Trả về object literal thì phải bọc ngoặc tròn: `() => ({ id: 1 })`

Điều thứ ba là bẫy kinh điển. Không có ngoặc tròn, JavaScript hiểu `{}` là thân hàm, nên hàm trả về `undefined` và bạn ngồi tìm lỗi cả buổi.

Về `this`: arrow function không có `this` riêng, nó dùng `this` của phạm vi bao ngoài. Với function component hiện đại bạn ít gặp chuyện này, nhưng đó là lý do các callback trong React luôn được viết bằng arrow function.

**Bài tập 2.** Viết lại hàm sau thành arrow function một dòng: `function nhan2(x) { return x * 2; }`

**Xem đáp án**

`const nhan2 = (x) => x * 2;`

## Template literal: ghép chuỗi bằng backtick

Dấu backtick `` ` `` cho phép chèn biểu thức bằng `${}` và viết chuỗi nhiều dòng mà không cần `\n`. Trong React, bạn dùng nó nhiều nhất ở hai chỗ: `className` động và URL API.

```js
const dangChon = true;
const lop = `menu-item ${dangChon ? "active" : ""}`;

const API_BASE = "https://api.example.com";
const url = `${API_BASE}/todos/${id}`;
```

**Bài tập 3.** Từ hai biến `ten = "Lan"` và `soViec = 3`, tạo chuỗi `Xin chào Lan, bạn có 3 việc cần làm`.

**Xem đáp án**

``const loi = `Xin chào ${ten}, bạn có ${soViec} việc cần làm`;``

## Destructuring: bóc dữ liệu ra khỏi object và array

```js
const sanPham = { id: 1, ten: "Bàn phím", gia: 500000 };

const { ten, gia } = sanPham;              // lấy đúng tên field
const { ten: tenSP, gia: giaSP } = sanPham; // đổi tên biến
const { ten = "Chưa có tên" } = sanPham;    // giá trị mặc định khi field thiếu

const diem = [9, 8, 7];
const [dau, hai] = diem;   // dau = 9, hai = 8
const [, , ba] = diem;     // bỏ qua phần tử đầu: ba = 7
```

Đây chính là lý do bài này quan trọng với React. Hai dòng code bạn sẽ gặp ở mọi component:

```jsx
const [count, setCount] = useState(0); // array destructuring

function TheSanPham({ ten, gia }) {    // destructuring ngay trong tham số
  return <div>{ten} - {gia}</div>;
}
```

**Bài tập 4.** Cho `const nguoiDung = { hoTen: "Minh", email: "minh@example.com" }`. Viết một dòng destructuring lấy `hoTen` vào biến tên `ten`.

**Xem đáp án**

`const { hoTen: ten } = nguoiDung;`

## Spread và rest: `...` làm hai việc khác nhau

Spread trải giá trị ra, rest gom giá trị lại. Cùng một ký hiệu, khác ngữ cảnh.

```js
// Spread: tạo bản sao
const cu = [1, 2, 3];
const moi = [...cu, 4];                    // [1, 2, 3, 4]

const user = { ten: "Lan", tuoi: 20 };
const capNhat = { ...user, tuoi: 21 };     // ghi đè đúng một field

// Rest: gom phần còn lại
const { ten, ...phanConLai } = user;
function tong(...cacSo) {
  return cacSo.reduce((a, b) => a + b, 0);
}
```

Trong React, spread là cách chuẩn để cập nhật state mà không sửa thẳng dữ liệu cũ. Mặc dù bài này chưa chạm tới `useState`, hãy nhớ sẵn hình mẫu `setTodos([...todos, viecMoi])` và `setUser({ ...user, ten: "Minh" })`.

Lưu ý: spread chỉ là **shallow copy**. Object lồng bên trong vẫn dùng chung tham chiếu với object gốc.

**Bài tập 5.** Cho `const hoaDon = { ma: "HD01", tong: 100, daThanhToan: false }`. Viết code tạo object mới đã thanh toán mà không sửa `hoaDon`.

**Xem đáp án**

`const daThanhToan = { ...hoaDon, daThanhToan: true };`

## Điền khuyết: kiểm tra nhanh cú pháp ES6

1. Từ ES6, ta nên dùng _____ làm mặc định khi khai báo biến, chỉ dùng let khi biến bị gán lại.
2. Arrow function không có _____ riêng, nó dùng của phạm vi bao ngoài.
3. `const [count, setCount] = useState(0)` là ví dụ của _____.
4. Để tạo bản sao object rồi ghi đè một field, ta viết `{ ...user, tuoi: 21 }`, trong đó `...` là _____ operator.
5. Muốn nối giá trị biến vào chuỗi từ ES6, ta dùng _____ với dấu backtick.
6. `const { ten: hoTen } = nguoi` lấy field `ten` nhưng _____ biến thành `hoTen`.

## Thẻ ghi nhớ ES6

Front: `const` khác `let` ở điểm nào?
Back: `const` không cho gán lại biến, `let` thì cho phép.

Front: Vì sao nên mặc định dùng `const`?
Back: Vì nó báo lỗi ngay khi vô tình gán lại, giúp code an toàn hơn.

Front: `const` khai báo object thì có sửa được thuộc tính không?
Back: Có, `const` chỉ chặn gán lại biến chứ không đóng băng nội dung object.

Front: Arrow function khác function thường ở điểm cốt lõi nào?
Back: Arrow function không có `this` riêng, nó dùng `this` của phạm vi bao ngoài.

Front: Arrow function trả về object literal phải viết thế nào?
Back: Bọc object trong ngoặc tròn: `() => ({ id: 1 })`.

Front: Khi nào bỏ được ngoặc đơn tham số của arrow function?
Back: Khi chỉ có đúng một tham số, ví dụ `x => x * 2`.

Front: Template literal dùng cặp ký tự gì để bao chuỗi?
Back: Dấu backtick, và chèn biểu thức bằng `${...}`.

Front: Object destructuring lấy field `ten` và đổi tên thành `hoTen` viết thế nào?
Back: `const { ten: hoTen } = nguoi;`

Front: Destructuring có hỗ trợ giá trị mặc định không?
Back: Có: `const { ten = 'Khách' } = nguoi;`

Front: `const [count, setCount] = useState(0)` dùng kỹ thuật gì?
Back: Array destructuring.

Front: Spread operator làm gì với object?
Back: Tạo bản sao nông và có thể ghi đè field: `{ ...user, ten: 'Minh' }`.

Front: Vì sao React cần spread khi cập nhật state?
Back: Vì không được mutate state trực tiếp, phải tạo object hoặc array mới.

Front: Rest khác spread ở đâu?
Back: Rest gom nhiều giá trị còn lại vào một biến, spread trải giá trị ra.

Front: Spread có copy sâu object lồng nhau không?
Back: Không, đó là shallow copy, object con vẫn chia sẻ tham chiếu.

## Bốn lỗi ES6 hay gặp khi bắt đầu với React

- **Sửa thẳng object thay vì tạo bản sao.** `user.ten = "Minh"` chạy được với `const`, nhưng React sẽ không thấy dữ liệu đổi. Luôn dùng `{ ...user, ten: "Minh" }`.
- **Quên ngoặc tròn khi arrow function trả về object.** `() => { id: 1 }` trả về `undefined`, phải là `() => ({ id: 1 })`.
- **Dùng `let` cho mọi thứ.** Thói quen này khiến biến bị gán lại mà không ai báo lỗi. Mặc định `const`, chỉ nâng lên `let` khi cần.
- **Quên rằng destructuring không tạo bản sao.** `const { ten } = user` vẫn trỏ tới cùng chuỗi, còn `const { diaChi } = user` thì `diaChi` vẫn là object gốc của `user`, sửa nó là sửa luôn `user`.

Mẹo nhanh: nếu bạn thấy dấu `+` đang nối chuỗi, gần như luôn có một template literal gọn hơn ở đó.

## Mang theo gì khi sang bài map, filter, reduce

Năm điều cần nhớ: `const` là mặc định, `let` chỉ khi biến đổi giá trị; arrow function ngắn gọn nhưng phải bọc ngoặc tròn khi trả về object; template literal thay cho nối chuỗi; destructuring lấy đúng field bạn cần; spread tạo bản sao thay vì sửa dữ liệu gốc.

Bài tiếp theo, **Hàm và mảng trong thực tế: map, filter, reduce**, sẽ dùng chính arrow function và destructuring bạn vừa học để biến một mảng dữ liệu thô thành danh sách hiển thị được trên giao diện.

---

## Contents

Part of [⚛️ React từ con số 0 cho người chỉ biết HTML](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html.md)

- **🧱 Nền tảng JavaScript và tư duy React**
  - [✨ ES6 thiết yếu cho React: let, const, arrow function, destructuring, spread](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/es6-thiet-yeu-cho-react.md) — this lesson
  - [🔁 Hàm và mảng trong thực tế: map, filter, reduce](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/ham-mang-map-filter-reduce.md) (sign-in required)
  - [🧩 Tư duy component và khởi tạo dự án với Vite](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/tu-duy-component-va-khoi-tao-vite.md)
  - [✅ Checkpoint: nền tảng JavaScript và tư duy React](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/checkpoint-nen-tang-javascript-va-react.md)
- **🧩 Component, JSX, props và state**
  - [📄 JSX và component đầu tiên](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/jsx-va-component-dau-tien.md)
  - [📦 Props và composition: truyền dữ liệu giữa component](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/props-va-composition.md)
  - [🔄 State với useState và xử lý sự kiện](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/state-usestate-va-su-kien.md)
  - [📋 Render danh sách và key trong React](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/render-danh-sach-va-key.md)
  - [✅ Checkpoint: component, JSX, props và state](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/checkpoint-component-va-state.md)
- **🚀 Form, useEffect, gọi API và dự án nhỏ**
  - [📝 Form và controlled components](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/form-va-controlled-components.md)
  - [⚙️ useEffect và side effects](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/useeffect-va-side-effects.md)
  - [🌐 Gọi API với fetch: loading, error và cleanup](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/goi-api-voi-fetch.md) (premium content)
  - [🛠️ Dự án: ứng dụng quản lý nhỏ với Vite](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/du-an-ung-dung-quan-ly-voi-vite.md) (premium content)
  - [✅ Checkpoint: form, useEffect, gọi API và dự án](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/checkpoint-form-api-va-du-an.md) (premium content)
- [Course cheatsheet](https://everwise.study/courses/react-tu-con-so-0-cho-nguoi-chi-biet-html/cheatsheet.md) (premium content)
