# Bạn muốn học gì?
Source: https://www.youhoc.com/index
Nền tảng cho mọi ngôn ngữ
Front-end Framework
# Arrow Function trong JavaScript
Source: https://www.youhoc.com/javascript/arrow-function
Khi bắt đầu làm việc với các stack như React, Node.js hay bất kỳ framework JavaScript nào, bạn sẽ thấy cú pháp `=>` xuất hiện khắp nơi - trong callback của `fetch`, trong các method như `.map()`, `.filter()`, hay trong các component của React. Nếu chưa quen với Arrow Function, code của người khác sẽ trông khá lạ lẫm.
Bài viết này là một "refresher" nhanh về Arrow Function, giúp bạn đọc và viết được cú pháp này trước khi bước vào học bất kỳ JavaScript stack nào.
***
## Arrow Function là gì?
Arrow Function là cú pháp rút gọn để khai báo function, được giới thiệu từ ES6 (2015). Thay vì viết `function() { ... }`, bạn dùng `() => { ... }`.
Ví dụ đơn giản nhất:
```js theme={null}
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
// [2, 4, 6, 8, 10]
```
Arrow Function được dùng nhiều nhất trong các callback như `.map()`, `.filter()`, `.then()`, vì nó giúp code ngắn gọn và dễ đọc hơn.
***
## Cách khai báo
### Function bình thường (function expression)
```js theme={null}
const add = function(a, b) {
return a + b;
};
```
### Arrow Function
```js theme={null}
const add = (a, b) => {
return a + b;
};
```
### Arrow Function rút gọn - nếu chỉ có 1 dòng `return`
Khi thân hàm chỉ có một biểu thức duy nhất để trả về, bạn có thể bỏ luôn `{}` và `return`:
```js theme={null}
const add = (a, b) => a + b;
```
Nếu chỉ có 1 tham số, bạn còn có thể bỏ cả dấu ngoặc `()`, siêu gọn:
```js theme={null}
const double = n => n * 2;
```
***
## Dùng Arrow Function như callback
Đây là nơi Arrow Function tỏa sáng nhất. So sánh 3 cách viết callback cho `.then()`:
```js theme={null}
// Function bình thường
.then(function(res) {
return res.json();
})
// Arrow Function
.then((res) => {
return res.json();
})
// Arrow Function rút gọn - cách viết phổ biến nhất
.then(res => res.json())
```
Cả 3 đều làm cùng một việc. Trong thực tế, bạn sẽ thường thấy cách rút gọn nhất.
***
## Function lồng Function
Một pattern hay gặp là truyền Arrow Function trực tiếp làm argument khi gọi hàm, thay vì phải khai báo riêng:
```js theme={null}
function greet(greetFunc, name) {
return greetFunc(name);
}
// Viết dài - khai báo riêng
console.log(
greet(function(name) { return 'Hi ' + name; }, 'Tony')
)
// Viết ngắn - truyền Arrow Fn trực tiếp
console.log(greet((name) => 'Hi ' + name, 'Tony'))
```
***
## Lưu ý quan trọng
### 1. Không có hoisting - phải khai báo trước khi dùng
Function bình thường được "hoisted" lên đầu file, nên bạn có thể gọi nó trước khi khai báo. Arrow Function thì không.
```js theme={null}
regular(); // chạy OK
arrow(); // Lỗi: Cannot access 'arrow' before initialization
function regular() {
console.log('Regular');
}
const arrow = () => console.log('Arrow');
```
### 2. Không có `this`
Đây là điểm khác biệt lớn nhất. Function bình thường tạo ra `this` riêng của nó, trỏ đến object đang gọi hàm. Arrow Function không tạo `this`, nên nó dùng `this` từ scope bên ngoài.
```js theme={null}
const person = {
name: 'Brad',
sayHelloRegular: function () {
console.log('Regular:', this.name); // "Brad"
},
sayHelloArrow: () => {
console.log('Arrow:', this.name); // undefined
},
};
person.sayHelloRegular(); // Regular: Brad
person.sayHelloArrow(); // Arrow: undefined
```
`sayHelloArrow` không có `this` của riêng nó, nên `this` ở đây trỏ ra scope bên ngoài object - là `{}` (trong Node.js ES Modules) hoặc `window` (trong browser). Cả hai đều không có thuộc tính `name`, nên kết quả là `undefined`.
**Khi nào nên dùng function bình thường?** Khi bạn cần truy cập `this`, ví dụ trong object methods hay class methods. Với các callback thuần túy không liên quan đến `this`, Arrow Function là lựa chọn tốt hơn.
***
## Tóm tắt
| | Function bình thường | Arrow Function |
| :------- | :------------------------------- | :--------------------------------- |
| Cú pháp | `function(a, b) { return ... }` | `(a, b) => ...` |
| Hoisting | Có | Không |
| `this` | Có (trỏ đến object gọi hàm) | Không (dùng `this` từ scope ngoài) |
| Dùng khi | Object/class methods, cần `this` | Callback, xử lý dữ liệu |
Arrow Function không phải là "phiên bản mới hơn" của function bình thường, mà là một công cụ khác phù hợp với những tình huống khác nhau. Trong thực tế, bạn sẽ dùng Arrow Function cho hầu hết các callback (`.map`, `.filter`, `.then`...), và dùng function bình thường khi cần `this`.
Khi đã quen với Arrow Function, bạn sẽ sẵn sàng hơn để đọc code trong React, Node.js, hay bất kỳ JavaScript stack nào khác.
# Tổng quan
Source: https://www.youhoc.com/javascript/index
Đang cập nhật
# 10 câu hỏi phỏng vấn Next.js thường gặp
Source: https://www.youhoc.com/next-js/10-interview-questions
Tổng hợp 10 câu hỏi phỏng vấn Next.js phổ biến từ junior đến mid-level, kèm gợi ý trả lời ngắn gọn, dễ nhớ và bám sát thực tế production.
Bạn vừa hoàn thành một project Next.js, tự tin apply vào vị trí Frontend Developer. Đến vòng technical, nhà tuyển dụng hỏi: *"Sự khác nhau giữa Server Component và Client Component là gì? Khi nào bạn dùng cái nào?"* — bạn ấp úng vì lâu nay chỉ copy `'use client'` lên đầu file cho... chắc ăn.
Next.js là framework rất "hot" trong các buổi phỏng vấn Frontend hiện nay, nhưng câu hỏi thường xoay quanh **một số ít chủ đề cốt lõi**. Nắm chắc chúng, bạn sẽ tự tin trả lời được 80% các vòng phỏng vấn.
Dưới đây là 10 câu hỏi phổ biến nhất, kèm gợi ý cách trả lời ngắn gọn — vừa đủ để gây ấn tượng, không lan man.
## 1. Next.js là gì? Khác gì so với React?
Đây gần như là câu "khởi động" trong mọi buổi phỏng vấn.
**Gợi ý trả lời:**
* **React** là một thư viện UI, chỉ lo phần render component phía client.
* **Next.js** là một framework xây trên React, bổ sung những thứ React thuần không có sẵn: file-based routing, Server-Side Rendering (SSR), Static Site Generation (SSG), tối ưu hình ảnh, API Routes, và gần đây nhất là **React Server Components**.
Nói ngắn gọn: *React lo phần UI, Next.js lo phần "còn lại" của một ứng dụng web hoàn chỉnh — routing, rendering, fetching, deployment.*
## 2. Phân biệt CSR, SSR, SSG và ISR
Câu này kiểm tra bạn có thực sự hiểu **các chiến lược render** hay không.
| Chiến lược | Khi nào render? | Use case |
| :---------------------------------------- | :--------------------------------- | :------------------------------------------------- |
| **CSR** (Client-Side Rendering) | Trong browser, sau khi JS tải xong | Dashboard nội bộ, không cần SEO |
| **SSR** (Server-Side Rendering) | Trên server, mỗi request | Trang có data thay đổi liên tục, cần SEO |
| **SSG** (Static Site Generation) | Lúc build | Blog, landing page, docs |
| **ISR** (Incremental Static Regeneration) | Lúc build + revalidate định kỳ | E-commerce, news — cập nhật không quá thường xuyên |
**Mẹo trả lời:** nhấn mạnh rằng trong App Router (Next.js 13+), bạn không còn dùng `getServerSideProps` hay `getStaticProps` nữa — mà điều khiển bằng `fetch` options (`cache`, `next.revalidate`) và **Server Components**.
## 3. Server Components và Client Components khác nhau ở đâu?
Đây là câu **dễ bị hỏi nhất** với Next.js 13+.
**Gợi ý trả lời:**
* **Server Component** (mặc định): chạy trên server, không gửi JS xuống client → bundle nhỏ hơn, fetch data trực tiếp được, không dùng được hook (`useState`, `useEffect`).
* **Client Component**: phải khai báo `'use client'` ở đầu file. Chạy trên browser, dùng được hook, event handler, browser API.
**Nguyên tắc vàng:** đặt `'use client'` **càng sâu trong cây component càng tốt**. Chỉ "client hoá" những phần thực sự cần tương tác.
```jsx theme={null}
// ❌ Sai: client hoá cả Header chỉ vì cần usePathname trong NavLink
'use client';
export default function Header() { /* ... */ }
// ✅ Đúng: tách NavLink ra component riêng
// header.js (Server Component)
import NavLink from './nav-link';
// nav-link.js (Client Component)
'use client';
import { usePathname } from 'next/navigation';
```
## 4. File-based routing hoạt động thế nào? Khác gì Pages Router?
**Gợi ý trả lời:**
Next.js dùng **cấu trúc thư mục làm routing**. Trong App Router:
* Mỗi thư mục = một segment URL.
* File `page.js` (hoặc `page.tsx`) định nghĩa nội dung trang.
* File `layout.js` định nghĩa khung bao quanh, hỗ trợ **nested layouts**.
* Các "reserved files" khác: `loading.js`, `error.js`, `not-found.js`, `route.js`.
Khác biệt chính so với **Pages Router** (cũ):
| Pages Router (`/pages`) | App Router (`/app`) |
| :------------------------------------- | :----------------------------- |
| `getServerSideProps`, `getStaticProps` | `fetch` trong Server Component |
| `_app.js`, `_document.js` | `layout.js` |
| Mọi component đều là client | Mặc định Server Component |
| `next/router` | `next/navigation` |
## 5. Dynamic Routes là gì? Làm sao truyền params vào trang?
**Gợi ý trả lời:**
Đặt tên thư mục trong dấu ngoặc vuông để tạo **dynamic segment**:
```text theme={null}
/app/blog/[slug]/page.js → /blog/hello-world
/app/shop/[...all]/page.js → catch-all: /shop/a/b/c
/app/shop/[[...all]]/page.js → optional catch-all
```
Trong component, `params` được truyền vào như một prop:
```jsx theme={null}
export default async function BlogDetail({ params }) {
const { slug } = await params; // Next.js 15+: params là Promise
const post = await getPost(slug);
return {post.title};
}
```
**Bonus:** đề cập `generateStaticParams()` để pre-render các slug lúc build (SSG cho dynamic routes).
## 6. Khi nào dùng ``, khi nào dùng `useRouter`?
**Gợi ý trả lời:**
* ``: dùng cho navigation **khai báo** (declarative) — khi user click vào một link. Hỗ trợ **prefetch** tự động và chuyển sang CSR khi đang ở trong app.
* `useRouter()` (từ `next/navigation`): dùng cho navigation **lập trình** (programmatic) — sau khi submit form, sau khi đăng nhập thành công, v.v.
```jsx theme={null}
'use client';
import { useRouter } from 'next/navigation';
const router = useRouter();
router.push('/dashboard');
router.replace('/login');
router.refresh(); // refetch Server Component
```
**Lưu ý:** `useRouter` chỉ dùng được trong Client Component. Ở Server Component, dùng `redirect()` từ `next/navigation`.
## 7. Data fetching trong App Router hoạt động ra sao?
**Gợi ý trả lời:**
Trong App Router, bạn fetch data trực tiếp trong **Server Component** bằng `async/await`:
```jsx theme={null}
export default async function PostsPage() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 }, // ISR: cache 60 giây
});
const posts = await res.json();
return ;
}
```
Có 3 chế độ chính, điều khiển qua option của `fetch`:
* `cache: 'force-cache'` (mặc định) → tương đương **SSG**
* `cache: 'no-store'` → tương đương **SSR**
* `next: { revalidate: N }` → tương đương **ISR**
Kết hợp với `loading.js` để hiển thị skeleton trong khi fetch, và `error.js` để xử lý lỗi.
## 8. API Routes / Route Handlers dùng để làm gì?
**Gợi ý trả lời:**
Next.js cho phép viết **backend ngay trong project** thông qua `route.js` (App Router) hoặc `/pages/api/*` (Pages Router).
```jsx theme={null}
// app/api/posts/route.js
export async function GET() {
const posts = await db.post.findMany();
return Response.json(posts);
}
export async function POST(request) {
const body = await request.json();
const post = await db.post.create({ data: body });
return Response.json(post, { status: 201 });
}
```
**Use case:**
* Webhook handler
* Proxy che giấu API key
* BFF (Backend for Frontend) đơn giản
* Xử lý form submit, upload file
**Lưu ý:** với mutation đơn giản, **Server Actions** (Next.js 14+) thường gọn hơn Route Handlers.
## 9. Tối ưu performance trong Next.js — bạn làm những gì?
Câu này test **kinh nghiệm thực chiến**. Liệt kê được nhiều ý là điểm cộng lớn:
* **`` từ `next/image`** — lazy loading, sinh `srcset`, dùng AVIF/WebP tự động.
* **`` với prefetch** — tải sẵn route khi link xuất hiện trong viewport.
* **`next/font`** — tự host font, tránh layout shift.
* **Server Components** — giảm JS bundle gửi xuống client.
* **Streaming** với `loading.js` và `` — hiển thị UI từng phần thay vì chờ toàn bộ data.
* **Dynamic import** (`next/dynamic`) — code-splitting cho component nặng (chart, editor).
* **Tránh `'use client'` ở root** — chỉ client hoá những gì thực sự cần.
* **Caching đúng cách** với `fetch` options và `revalidateTag` / `revalidatePath`.
## 10. Bạn deploy Next.js ở đâu? Vì sao?
Câu hỏi mang tính **trải nghiệm**, không có đáp án đúng/sai.
**Gợi ý trả lời:**
* **Vercel**: đơn giản nhất, hỗ trợ đầy đủ mọi tính năng Next.js (ISR, Image Optimization, Edge Functions). Nhược: giá cao khi scale.
* **Self-host (Docker + Node.js)**: linh hoạt, kiểm soát chi phí, nhưng phải tự lo Image Optimization, caching, CDN.
* **Cloudflare Pages / Netlify / AWS Amplify**: tốt cho dự án nhỏ, nhưng một vài tính năng (ISR, middleware) có thể giới hạn.
Nếu có kinh nghiệm thực tế, hãy kể câu chuyện cụ thể: *"Mình từng deploy một blog SSG trên Vercel free tier, sau đó migrate sang VPS dùng Docker để giảm chi phí khi traffic tăng..."* — luôn ăn điểm.
## Một vài golden rules khi trả lời phỏng vấn Next.js
* **Đừng trả lời chung chung.** "Next.js có SSR" là chưa đủ — hãy nói **khi nào** dùng SSR và **vì sao**.
* **Luôn so sánh với Pages Router.** Người phỏng vấn thường muốn biết bạn có hiểu sự thay đổi từ Next.js 12 → 13+ không.
* **Nhắc đến caching.** App Router có hệ thống cache 4 tầng (Request Memoization, Data Cache, Full Route Cache, Router Cache) — nắm sơ là điểm cộng lớn.
* **Đừng "phun" buzzword.** Nếu nói "React Server Components" thì phải giải thích được nó là gì, khác Client Component ra sao.
* **Sẵn sàng cho câu hỏi sâu hơn.** Sau câu "SSR là gì?" thường sẽ là "Streaming SSR khác gì SSR truyền thống?".
## Tổng kết
10 câu hỏi trên gần như bao trùm các chủ đề bạn sẽ gặp trong phỏng vấn Next.js cho vị trí Junior đến Mid-level:
1. Next.js vs React
2. CSR / SSR / SSG / ISR
3. Server vs Client Components
4. File-based routing & App vs Pages Router
5. Dynamic Routes
6. `` vs `useRouter`
7. Data fetching trong App Router
8. API Routes / Route Handlers
9. Tối ưu performance
10. Deployment
Nếu muốn đi xa hơn, hãy tìm hiểu thêm các chủ đề nâng cao thường xuất hiện ở vòng senior:
* **Server Actions** và `useFormState`, `useFormStatus`
* **Middleware** và **Edge Runtime**
* **Caching strategies**: `revalidateTag`, `revalidatePath`, `unstable_cache`
* **Parallel Routes** và **Intercepting Routes**
* **Internationalization (i18n)** trong App Router
Chúc bạn pass phỏng vấn dễ dàng!
# 9 điều cơ bản đầu tiên khi đến với Next.js
Source: https://www.youhoc.com/next-js/9-starter-notes
Next.js không thay thế React — nó là một framework xây dựng trên nền React, bổ sung những thứ mà React “vanilla” không có sẵn: Server-Side Rendering (SSR), file-based routing, tối ưu hình ảnh, và nhiều hơn nữa.
Bạn đã quen với React — tạo component, quản lý state, render UI. Nhưng khi ứng dụng cần SEO tốt hơn, tốc độ tải trang nhanh hơn, hay routing không cần cài thêm thư viện… bạn bắt đầu nghe đến **Next.js**.
Next.js không thay thế React — nó là một framework *xây dựng trên nền React*, bổ sung những thứ mà React “vanilla” không có sẵn: Server-Side Rendering (SSR), file-based routing, tối ưu hình ảnh, và nhiều hơn nữa.
Bài viết này tóm tắt 11 khái niệm cốt lõi bạn sẽ gặp ngay trong bất cứ buổi học đầu tiên nào về Next.js.
## 1. Làm quen với “file-based routing”: tạo route bằng folder
Với React Router, bạn phải khai báo route bằng code.
Next.js làm điều đó theo cách khác: **cấu trúc thư mục chính là routing**.
```text theme={null}
/app
├── page.js → example.com/
├── /about
│ └── page.js → example.com/about
└── /blog
├── page.js → example.com/blog
└── /post-1
└── page.js → example.com/blog/post-1
```
Mỗi thư mục là một segment của URL. Muốn có route mới? Tạo thư mục mới và đặt `page.js` bên trong.
## 2. Hai “reserved files” quan trọng nhất: `page.js` và `layout.js`
Next.js có một hệ thống **reserved filenames** — những tên file đặc biệt mà framework nhận ra và xử lý theo cách riêng.
```text theme={null}
/app
├── layout.js ← app shell (master layout, bao toàn bộ app)
├── page.js
└── /about
├── layout.js ← nested layout, chỉ áp dụng cho /about
└── page.js
```
Hai file cơ bản nhất:
* `page.js` — định nghĩa nội dung của một trang, đây là file bắt buộc để một route được render.
* `layout.js` — định nghĩa “khung” bao quanh trang, ví dụ header, footer, sidebar. Layout lồng nhau (nested layout) cũng được hỗ trợ — `layout.js` trong thư mục con chỉ áp dụng cho trang đó và các trang con của nó.
Trong `layout.js` thường có metadata, thẻ `` và ``, và `{children}` — placeholder để render các trang con.
## 3. Các reserved filenames khác cần biết
Next.js còn nhiều tên file đặc biệt khác:
| File | Tác dụng |
| :------------- | :--------------------------------------------- |
| `not-found.js` | Hiển thị khi route không tồn tại (lỗi 404) |
| `error.js` | Fallback khi có lỗi xảy ra |
| `loading.js` | Hiển thị trong khi trang đang fetch data |
| `route.js` | Tạo API endpoint (trả về JSON, không phải JSX) |
| `icon.png` | Tự động dùng làm favicon |
Chi tiết đầy đủ tại [tài liệu chính thức của Next.js](https://nextjs.org/docs/app/api-reference/file-conventions).
## 4. Component `` — navigate thông minh hơn
Thay vì dùng thẻ `` thông thường, Next.js cung cấp component ``:
```jsx theme={null}
import Link from 'next/link';
About
```
Điểm hay của việc sử dụng Link là khi truy cập trực tiếp vào URL, Next.js sẽ **SSR** (render phía server).
Khi bạn đang đứng trong ứng dụng và click link, nó chuyển sang **CSR** — chỉ load phần component của route mới, không reload toàn trang. Tốt nhất của cả hai thế giới.
## 5. Dynamic Routes — route với tham số động
Để xử lý các URL dạng `/blog/post-1`, `/blog/post-2`… bạn có thể dùng **dynamic segment** bằng cách đặt tên thư mục trong dấu ngoặc vuông:
```text theme={null}
/app
└── /blog
├── page.js
└── /[slug]
└── page.js → example.com/blog/:slug
```
Trong component, `params` được truyền vào như một prop mặc định:
```jsx theme={null}
export default function BlogDetail({ params }) {
return