Câu 35: Webpack là gì? Vai trò trong React?
Webpack là một module bundler — nó đọc toàn bộ các file JS, CSS, image… của project, xử lý các dependency giữa chúng, rồi đóng gói lại thành một (hoặc vài) file tối ưu để trình duyệt tải về.
Trong dự án React, Webpack thường đảm nhiệm: đóng gói module, gọi Babel để transpile JSX/ES6+, tách code (code splitting), tối ưu bundle cho production.
Thực tế hiện nay: Với các project dùng Vite, bạn gần như không cần cấu hình Webpack nữa — Vite dùng esbuild và Rollup dưới hood, nhanh hơn đáng kể so với Webpack, đặc biệt ở bước dev server khởi động.
Câu 36: Babel trong React là gì?
Babel là một JavaScript transpiler — nó biên dịch code JSX và cú pháp JavaScript hiện đại (ES6+) thành JavaScript mà các trình duyệt cũ có thể hiểu được.
Ngoài JSX, Babel còn xử lý các tính năng như arrow functions, destructuring, async/await, optional chaining… đảm bảo code chạy được trên nhiều môi trường khác nhau.
Câu 37: Trình duyệt đọc file JSX như thế nào?
Trình duyệt không thể đọc JSX trực tiếp — JSX không phải JavaScript hợp lệ. Trước khi deploy, JSX phải được transpile (biên dịch) thành JavaScript thuần thông qua một bước build.
Trong thực tế, quá trình này diễn ra tự động trong build pipeline:
Với Vite, bước này xảy ra cực nhanh nhờ esbuild — bạn chỉ cần chạy npm run dev và mọi thứ được xử lý tự động.
Câu 38: Tại sao React không theo mô hình MVC truyền thống?
MVC truyền thống gặp vấn đề khi ứng dụng phình to: Model và View có thể cập nhật lẫn nhau theo nhiều chiều, tạo ra luồng dữ liệu phức tạp, khó debug — Facebook gọi đây là vấn đề “cascading updates”.
React giải quyết bằng cách áp dụng Unidirectional Data Flow: dữ liệu chỉ chảy một chiều từ cha xuống con qua props, còn thay đổi state được xử lý tập trung và có thể dự đoán được. Đây chính là lý do React (và Flux/Redux) ra đời.
Câu 39: JSX nhiều dòng viết như thế nào?
Khi JSX có nhiều dòng, bọc toàn bộ trong dấu ngoặc tròn () để tránh lỗi do JavaScript tự động thêm dấu chấm phẩy:
Câu 40: Reducer trong React là gì?
Reducer là một hàm thuần túy nhận vào state hiện tại và một action, rồi trả về state mới — không được mutate state cũ.
useReducer là lựa chọn tốt hơn useState khi state có logic phức tạp, nhiều trường hợp update khác nhau — hoặc khi muốn tách logic ra khỏi component.
Câu 41: Khi nào nên dùng Class Component thay vì Function Component?
Câu trả lời ngắn: Hầu như không còn lý do nào để chọn Class Component cho code mới kể từ khi Hooks ra đời (React 16.8).
Function Component với Hooks có thể làm được mọi thứ Class Component làm được — state (useState), lifecycle (useEffect), context (useContext)… — với code ngắn hơn và dễ test hơn.
Trường hợp duy nhất bạn buộc phải dùng Class Component là khi implement Error Boundary (vì chưa có hook tương đương). Còn lại, nếu đang maintain codebase cũ dùng Class Component, không cần rewrite — chúng vẫn hoạt động bình thường.
Câu 42: Cách chia sẻ dữ liệu giữa các component như thế nào?
Tùy vào mức độ “xa” giữa các component:
Component cha → con: truyền qua props
Component con → cha: truyền callback function qua props
Anh em (sibling): lift state up — đưa state lên component cha chung, rồi truyền xuống cả hai
Nhiều tầng / toàn app: dùng React Context, hoặc thư viện state management như Zustand, Redux
Câu 43: Reconciliation trong React là gì?
Reconciliation là quá trình React so sánh Virtual DOM mới với Virtual DOM cũ (sau mỗi lần state/props thay đổi) để tìm ra sự khác biệt nhỏ nhất cần cập nhật lên Real DOM.
Thay vì re-render toàn bộ trang, React chỉ “vá” đúng những phần thực sự thay đổi — đây là lý do tại sao React nhanh dù phải cập nhật UI liên tục.
Thuật toán so sánh này gọi là “diffing algorithm”, và key prop (câu 28) đóng vai trò quan trọng giúp thuật toán này hoạt động chính xác với danh sách.
Câu 44: Cách re-render component mà không dùng setState?
Với class component, có thể dùng forceUpdate() — ép React re-render bất kể state có thay đổi hay không. Tuy nhiên đây là cách làm không được khuyến nghị vì nó bypass cơ chế tối ưu của React.
Với functional component, không có forceUpdate. Cách thường dùng nhất là dùng một state dummy:
Trong thực tế, nếu bạn cần forceUpdate, thường là dấu hiệu state/data chưa được quản lý đúng cách — hãy xem lại cấu trúc state thay vì dùng cách này.
Câu 45: Có thể update props trong React không?
Không. Props là read-only (bất biến) — component con không bao giờ được phép tự thay đổi props mà nó nhận vào. Đây là nguyên tắc cốt lõi của React để đảm bảo luồng dữ liệu một chiều.
Nếu cần thay đổi dữ liệu đó, cách đúng là: component con gọi một callback function được truyền xuống từ cha, rồi cha cập nhật state của mình — khi state cha thay đổi, props mới sẽ tự động được truyền xuống con.
Câu 47: Destructuring trong React là gì?
Destructuring là cú pháp ES6 cho phép “giải nén” giá trị từ object hoặc array vào các biến riêng lẻ — được dùng rất phổ biến trong React, đặc biệt khi nhận props.
Câu 48: memo và useMemo trong React là gì? Khác nhau như thế nào?
Cả hai đều dùng để tối ưu hiệu suất bằng cách tránh tính toán hoặc render không cần thiết — nhưng chúng giải quyết hai vấn đề khác nhau.
React.memo — bọc quanh một component, ngăn component đó re-render nếu props không thay đổi:
useMemo — cache lại kết quả của một phép tính, chỉ tính lại khi dependency thay đổi:
Lưu ý quan trọng: Không nên dùng memo/useMemo ở khắp nơi — mỗi lần cache cũng tốn chi phí so sánh. Chỉ dùng khi component thực sự render nhiều lần không cần thiết, hoặc phép tính thực sự nặng. Với React Compiler (stable từ 2025), nhiều trường hợp này được tự động tối ưu mà không cần viết thủ công.
Câu 49: useRef là gì? Dùng như thế nào với input form?
useRef trả về một object { current: ... } tồn tại xuyên suốt vòng đời component — thay đổi .current không trigger re-render, đây là điểm khác biệt cốt lõi so với useState.
useRef có hai use case chính:
1. Truy cập trực tiếp DOM element — thường dùng với form input:
2. Lưu giá trị giữa các lần render mà không gây re-render — ví dụ lưu interval ID, previous value:
: Dùng useRef để đọc input là cách viết uncontrolled (React không quản lý giá trị). Với controlled input, bạn dùng useState + onChange — phức tạp hơn nhưng linh hoạt hơn (validate realtime, format khi gõ…). Trong thực tế, các thư viện form như React Hook Form tận dụng useRef để tối ưu hiệu suất, tránh re-render sau mỗi lần gõ phím.
Câu 50: useCallback là gì? Khi nào nên dùng?
useCallback cache lại một function, chỉ tạo function mới khi dependency thay đổi — ngăn component con bị re-render không cần thiết khi nhận function qua props.
Vấn đề nếu không dùng useCallback:
Giải quyết bằng useCallback:
useCallback thường đi kèm với React.memo — nếu component con không được bọc bằng memo, việc cache function cũng không có tác dụng vì con vẫn re-render bình thường.
Tóm tắt bộ ba tối ưu:
Tổng kết
Qua 50 câu hỏi, có thể thấy các chủ đề trọng tâm thường gặp trong phỏng vấn React xoay quanh:
Core concepts: Component, JSX, Virtual DOM, Reconciliation Data flow: Props, State, Context, Lifting State Up Hooks: useState, useEffect, useContext, useReducer Patterns: HOC, Pure Component, Error Boundary, Portal Tooling: Babel, Webpack/Vite, React Router Nếu bạn đã nắm chắc các khái niệm trên, bước tiếp theo nên tìm hiểu sâu hơn về React 19 features (Actions, Server Components), state management (Zustand, Redux Toolkit), performance optimization (memo, useMemo, useCallback), và testing (React Testing Library, Vitest).