- JSX là gì và tại sao React sử dụng nó?
JSX là cú pháp cho phép viết thẻ giống HTML ngay trong file JavaScript. Nó không phải là một ngôn ngữ riêng — trình duyệt hoàn toàn không hiểu JSX, mà Babel hoặc SWC dịch nó thành lời gọi hàm trước khi code chạy. Hình…
- Trình duyệt không hiểu JSX — vậy cuối cùng JSX chạy thành gì?
JSX được compiler dịch thành lời gọi hàm tạo element — React.createElement(type, props, ...children) ở bản cũ, và jsx() từ react/jsx-runtime kể từ React 17. Kết quả trả về không phải DOM node, mà là một object mô tả thuần: { type: 'h1', props: {…
- Trong React, render có điều kiện làm bằng những cách nào?
Conditional rendering trong React không có cú pháp riêng — bạn dùng đúng biểu thức JavaScript bình thường. Vì JSX chỉ là lời gọi hàm, mọi thứ trả về giá trị đều nhúng được vào ngoặc nhọn. Ba cách hay dùng, theo thứ tự từ…
- React Fragment là gì và khi nào nên sử dụng?
Fragment cho phép một component trả về nhiều phần tử cùng cấp mà không thêm thẻ bọc nào vào DOM. Viết đầy đủ là <React.Fragment, viết tắt là <...</. Hai chỗ Fragment không chỉ là dọn dẹp mà là bắt buộc: - HTML có ràng…
- Key prop trong React là gì và tại sao nó quan trọng?
key là cách bạn nói cho React biết phần tử nào trong danh sách là phần tử nào giữa hai lần render. Không có nó, React chỉ còn vị trí trong mảng để so — và vị trí thì thay đổi mỗi khi bạn chèn,…
- Sự khác nhau giữa biểu thức và câu lệnh trong JSX là gì?
Biểu thức (expression) là đoạn code trả về một giá trị, còn câu lệnh (statement) là đoạn code thực thi một hành động nhưng không trả về giá trị. Trong cặp dấu {} của JSX, bạn chỉ có thể đặt biểu thức, không thể đặt…
- Event handling trong JSX khác gì so với HTML thuần?
Khác ba chỗ: tên viết camelCase, giá trị là tham chiếu hàm chứ không phải chuỗi, và không có return false. Bên dưới còn một khác biệt lớn hơn ba cái đó — React không gắn listener lên từng thẻ. Cặp ngoặc cuối là lỗi…
- Spread operator trong JSX props được dùng như thế nào?
Spread operator trong JSX là cú pháp {...object} để bung tất cả key-value của một object ra thành các props riêng lẻ truyền vào component. Khi viết <Button {...btnProps} /, JSX compiler chuyển thành React.createElement(Button, btnProps). Nếu có key trùng, props viết trực tiếp trên…
- Khi render trong JSX, giá trị nào bị React bỏ qua và giá trị nào hiện ra màn hình?
React bỏ qua null, undefined, true và false; nhưng số 0 và chuỗi thì render ra màn hình. Chuỗi rỗng cũng không hiện gì, nhưng nó không nằm trong nhóm bị bỏ qua — nó vẫn là một giá trị React đem đi render, chỉ…
- Tại sao mỗi component React chỉ có thể return một element duy nhất ở cấp cao nhất?
Vì JSX dịch thành lời gọi hàm, và một hàm JavaScript chỉ trả về được một giá trị. Ràng buộc này không phải luật riêng của React — nó là ràng buộc của chính ngôn ngữ. Đoạn thứ hai là lỗi cú pháp JavaScript thuần,…
- props.children là gì và dùng khi nào?
props.children chứa mọi thứ bạn đặt giữa thẻ mở và thẻ đóng của một component. Nó là prop bình thường, chỉ khác ở chỗ JSX tự điền giá trị cho nó thay vì bạn viết tay. Hai đoạn dưới đây tương đương nhau — cho…
- Codebase cũ dùng `React.PureComponent` — chuyển sang function component thì thay bằng gì, và có tương đương hoàn toàn không?
Thay bằng React.memo, nhưng hai thứ không tương đương hoàn toàn: PureComponent so cả props lẫn state, còn memo chỉ so props. PureComponent là class kế thừa thay cho Component, tự cài sẵn shouldComponentUpdate bằng phép so sánh nông trên this.props và this.state. memo là…
- Controlled Component là gì trong React? Nêu điểm khác biệt với Uncontrolled Component.
Controlled Component (Component được kiểm soát) là component mà giá trị của các form element (như <input, <textarea, <select) được kiểm soát hoàn toàn bởi React state. - Thay vì để DOM tự quản lý trạng thái, React state sẽ là source of truth duy…
- Component composition là gì và tại sao nên dùng thay vì inheritance (kế thừa)?
Component Composition là kỹ thuật xây dựng các component phức tạp bằng cách "lắp ráp" hoặc "chứa" các component đơn giản hơn (giống như Lego), thay vì dùng cơ chế kế thừa (inheritance) của Lập trình Hướng đối tượng (OOP). Tại sao React khuyến khích…
- Forwardref trong React là gì và khi nào cần dùng?
- Stateless và stateful component khác nhau như thế nào?
Stateless component là component không quản lý state nội bộ; nó chỉ nhận props và render UI dựa trên props đó. Stateful component là component có state nội bộ, thường dùng để lưu dữ liệu thay đổi theo thời gian hoặc tương tác người dùng.…
- Compound Components pattern là gì?
Compound Components là pattern trong React cho phép bạn xây dựng một nhóm component phối hợp với nhau để tạo thành một UI duy nhất, trong đó component cha nắm giữ state và logic, còn các component con chia sẻ state đó một cách ngầm…
- Sự khác biệt giữa mount, update và unmount trong vòng đời component là gì?
Trong vòng đời (lifecycle) của một component React, có 3 giai đoạn chính: 1. Mount (Gắn kết): Là khoảnh khắc component được tạo ra và chèn vào DOM thật lần đầu tiên. - Hook tương ứng: useEffect với dependency array rỗng []. 2. Update (Cập…
- React component có thể return gì ngoài JSX?
Component chỉ cần trả về một giá trị React biết cách render — không nhất thiết là JSX element. Từ React 16 trở đi, danh sách này rộng hơn nhiều người tưởng. Các kiểu trả về hợp lệ: - null, undefined, false, true — React…
- Props và state khác nhau ở đâu?
Props là dữ liệu component nhận từ bên ngoài và không được sửa; state là dữ liệu component tự giữ và tự đổi. Ranh giới nằm ở chỗ ai sở hữu giá trị đó. Hình dung một hàm: props là tham số truyền vào, state…
- Lifting state up là gì và khi nào cần làm?
Lifting state up là chuyển state lên component cha chung gần nhất khi có từ hai component trở lên cần cùng một dữ liệu. Vì dữ liệu trong React chảy một chiều từ trên xuống, hai component anh em không nói chuyện trực tiếp được…
- Immutability trong React state là gì và tại sao quan trọng?
Bất biến ở đây nghĩa là không sửa object hay array đang nằm trong state, mà tạo bản mới rồi đưa vào setter. Lý do rất cụ thể: React quyết định có render lại hay không bằng Object.is trên giá trị cũ và mới —…
- Cập nhật state lồng nhau thế nào cho đúng?
Phải tạo bản sao mới ở mọi cấp nằm trên đường đi tới giá trị cần đổi. React so state cũ và mới bằng Object.is, tức so tham chiếu — sửa tại chỗ rồi gọi setter thì React thấy "vẫn là object cũ" và bỏ…
- Derived state là gì và những vấn đề thường gặp?
Derived state là dữ liệu được tính toán từ props hoặc state đã có, không phải dữ liệu lưu trữ riêng. Thay vì copy props vào useState, bạn tính giá trị mỗi lần render. Vấn đề thường gặp nhất là đồng bộ state với props:…
- State batching trong React là gì? Thay đổi trong React 18?
- Unidirectional data flow trong React nghĩa là gì?
Unidirectional Data Flow (Luồng dữ liệu một chiều) trong React có nghĩa là: - Dữ liệu luôn chảy theo một hướng duy nhất: Từ Component cha xuống Component con (thông qua props). - Component con không bao giờ được phép thay đổi trực tiếp props…
- Khi nào state update là synchronous, khi nào là asynchronous?
- Tại sao không nên khởi tạo state từ props trực tiếp?
- `componentDidMount` tương đương gì trong function component, và chỗ nào không tương đương?
Gần nhất là useEffect(() = { ... }, []), nhưng hai thứ không trùng khít: thời điểm chạy khác nhau, và trong Strict Mode ở môi trường phát triển thì số lần chạy cũng khác. componentDidMount chạy đúng một lần, ngay sau khi component được…
- componentDidUpdate hoạt động như thế nào và khi nào nên dùng?
componentDidUpdate(prevProps, prevState) được gọi sau mỗi lần re-render (trừ lần đầu mount). So sánh prevProps/prevState với giá trị hiện tại để quyết định có nên thực hiện side effects không. Luôn wrap code trong điều kiện if (prevProps.id !== this.props.id) để tránh infinite loop.
- `componentWillUnmount` tương đương gì ở hook, và bỏ quên nó thì rò rỉ ra sao?
Tương đương là hàm cleanup trả về từ useEffect — nhưng nó chạy nhiều hơn componentWillUnmount: trước mỗi lần effect chạy lại, chứ không chỉ lúc unmount. Khác biệt này là điểm cộng chứ không phải phiền toái: nó ép bạn viết phần huỷ ngay…
- shouldComponentUpdate hoạt động như thế nào và khi nào nên dùng?
- componentDidCatch và Error Boundary liên quan như thế nào?
componentDidCatch(error, info) là lifecycle method cho phép Class Component bắt lỗi từ component con trong render phase. Kết hợp với getDerivedStateFromError để tạo Error Boundary - component bắt lỗi và hiển thị fallback UI. Function components không thể là Error Boundary, phải dùng class hoặc…
- Thứ tự lifecycle methods khi component mount, update, unmount là gì?
Thứ tự lifecycle methods qua 3 giai đoạn: - Mount: constructor → getDerivedStateFromProps → render → DOM update → componentDidMount. - Update: getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → DOM update → componentDidUpdate. - Unmount: componentWillUnmount → component bị xoá. - Với concurrent mode,…
- Strict Mode ảnh hưởng đến lifecycle như thế nào?
- useState hook hoạt động như thế nào?
useState trả về một cặp: giá trị hiện tại và hàm để đổi nó. Gọi hàm setter không sửa biến tại chỗ — nó lên lịch cho React render lại component với giá trị mới. Điểm khiến người mới vấp: count là hằng số trong…
- Dependency array của useEffect quyết định điều gì?
Dependency array là danh sách những giá trị mà effect phụ thuộc vào; React chạy lại effect khi một trong số đó đổi. Nó không phải bộ hẹn giờ hay công tắc — nó là lời khai báo "effect này đọc những thứ này". Ba…
- Cleanup function trong useEffect là gì và khi nào cần dùng?
Cleanup là hàm bạn trả về từ useEffect; React gọi nó trước mỗi lần chạy lại effect và một lần nữa khi component unmount. Nó không phải "hàm dọn dẹp lúc thoát" — nó chạy nhiều lần trong đời một component. Nếu delay đổi, React…
- Vì sao không truyền thẳng hàm `async` vào useEffect, và viết đúng thì viết thế nào?
Vì useEffect dùng giá trị trả về của callback làm hàm cleanup, mà hàm async luôn trả về một Promise. React sẽ cầm Promise đó và cố gọi nó như một hàm khi dọn dẹp. Phần AbortController không phải trang trí. Effect có thể chạy…
- Làm sao tránh infinite loop trong useEffect?
Vòng lặp vô hạn xảy ra khi effect cập nhật chính thứ mà nó phụ thuộc vào. Set state → render lại → dependency đổi → effect chạy → set state. Chuỗi này không tự dừng. Ba nguyên nhân phổ biến và cách chữa tương…
- Stale closure trong useEffect là gì và cách tránh?
Stale closure là khi một hàm vẫn nhìn thấy giá trị của lần render đã cũ. Nó không phải lỗi của React mà là hệ quả bình thường của closure trong JavaScript: mỗi lần render tạo ra một bộ biến mới, và hàm nào được…
- Lazy initialization của useState là gì và khi nào dùng?
- Lên React 18, useEffect chạy hai lần lúc dev — vì sao, và có nên chặn không?
Trong Strict Mode ở môi trường phát triển, React 18 cố ý chạy effect hai lần: mount → cleanup → mount lại. Đây không phải lỗi và cũng không xảy ra ở production — nó là bài kiểm tra xem effect của bạn có dọn…
- useInsertionEffect là gì và khi nào dùng?
- Hai component cùng dùng một custom hook thì có dùng chung state không?
Không. Mỗi component gọi hook nhận một bản state riêng — custom hook chia sẻ logic, không chia sẻ dữ liệu. Đây là chỗ tên gọi gây hiểu nhầm. "Share stateful logic" nghe như hai component sẽ thấy cùng một giá trị, nhưng custom hook…
- useEffect với object dependencies có vấn đề gì?
- Cách đúng để fetch data và xử lý race conditions trong useEffect?
Race condition xảy ra khi effect chạy lại trước lúc request cũ trả về — hai response về không đúng thứ tự và bản cũ ghi đè bản mới. Không có gì báo lỗi; giao diện chỉ đơn giản hiện sai dữ liệu. Hình dung…
- useContext hook là gì và cách sử dụng?
useContext là hook giúp component đọc giá trị từ React Context mà không cần truyền props qua từng cấp. Bạn truyền vào object tạo bởi createContext, hook trả về value của Provider gần nhất phía trên trong cây. Hãy hình dung Context như bảng thông…
- useMemo hook dùng để làm gì? Khi nào nên dùng?
useMemo memoize kết quả tính toán tốn kém, chỉ tính lại khi dependencies thay đổi. Dùng khi có tính toán expensive mà không muốn chạy lại mỗi render, hoặc cần stable object reference. Không nên dùng quá mức vì có overhead riêng.
- useCallback hook dùng để làm gì? Khác gì useMemo?
useCallback memoize function để giữ stable reference giữa renders. Dùng khi truyền callback xuống child component được wrap bởi React.memo, hoặc khi function là dependency của useEffect.
- useRef hook có những công dụng gì?
useRef tạo một mutable object có property .current sống xuyên suốt vòng đời component, và thay đổi .current không trigger re-render. Ví von: useRef giống một chiếc hộp nhỏ bạn gắn vào component. Bạn mở hộp ra, bỏ gì vào cũng được, lấy ra bất…
- useTransition hook dùng để làm gì?
- useDeferredValue hook là gì?
- useImperativeHandle hook dùng để làm gì?
- useSyncExternalStore hook là gì?
- Rules of Hooks gồm những gì, và vì sao không được gọi hook trong `if`?
Hai quy tắc: chỉ gọi hook ở cấp cao nhất của hàm, và chỉ gọi trong function component hoặc custom hook. Cả hai đều xuất phát từ một chi tiết cài đặt — React nhận diện hook theo thứ tự gọi, không theo tên. React…
- useOptimistic hook (React 19) là gì?
- useActionState hook (React 19) là gì?
- Cách tối ưu useContext để tránh re-render không cần thiết?
Mọi component gọi useContext đều render lại khi giá trị của Provider đổi — kể cả khi nó chỉ đọc một field không liên quan. Context không có cơ chế đăng ký theo từng phần; nó so sánh cả object bằng Object.is. Lỗi phổ biến…
- Sự khác biệt giữa useMemo và React.memo là gì?
useMemo là hook memoize giá trị/kết quả tính toán bên trong component. React.memo là HOC memoize toàn bộ component, skip re-render khi props không thay đổi (shallow comparison). Kết hợp cả hai: dùng React.memo cho component, useCallback cho callback props để React.memo hoạt động hiệu…
- Custom hook là gì và cách tạo?
Custom hook là JavaScript function bắt đầu bằng 'use' có thể gọi các hooks khác. Dùng để tái sử dụng stateful logic giữa components. Mỗi component sử dụng custom hook có state instance riêng biệt, không chia sẻ.
- Khi nào nên tách logic vào custom hook so với utility function?
Dùng custom hook khi logic cần: React hooks (useState, useEffect, v.v.), React lifecycle, hay stateful behavior. Dùng utility function (pure function) khi: chỉ xử lý data transformation, validation, formatting - không cần React context. Custom hook gọi được từ components, utility function gọi từ bất…
- Viết custom hook useDebounce như thế nào?
useDebounce delay việc cập nhật value cho đến khi user ngừng thay đổi trong khoảng thời gian nhất định:
- Làm thế nào để test custom hooks?
- usePrevious hook làm gì và cách implement?
usePrevious lưu giá trị trước đó của một value sử dụng useRef. Sau mỗi render, ref được cập nhật với value hiện tại nhưng function trả về ref.current (value từ render trước).
- Composition của custom hooks là gì?
- Patterns hay được dùng trong custom hooks là gì?
- Context API trong React là gì và giải quyết vấn đề gì?
Context API cho phép chia sẻ dữ liệu (theme, language, auth, user) qua component tree mà không cần pass props qua từng cấp trung gian (props drilling). Gồm ba phần: createContext, Provider, useContext.
- Khi nào nên dùng Context thay vì props drilling?
Dùng Context khi: dữ liệu cần ở nhiều levels sâu (theme, locale, auth), data được nhiều components dùng, props chỉ passed qua để forward (không dùng ở cấp trung gian). Không nên dùng cho state thay đổi thường xuyên vì gây nhiều re-renders. Props drilling…
- useParams hook trong React Router dùng để làm gì?
useParams trả về object chứa các dynamic segment của URL route đang active. Ví dụ route /users/:id khi truy cập /users/42 thì const { id } = useParams() trả về id = '42'. Lưu ý giá trị luôn là string, cần tự convert nếu cần…
- useNavigate hook trong React Router v6 dùng như thế nào?
useNavigate trả về navigate function để programmatically điều hướng: navigate('/path'), navigate(-1) (back), navigate('/path', { replace: true }). Thay thế cho useHistory trong v5. Dùng khi cần navigate sau form submit, sau auth login, hay trong event handlers không phải JSX.
- Nested routes trong React Router v6 hoạt động như thế nào?
Nested route dùng component <Outlet / làm chỗ cắm cho route con. Route cha render layout dùng chung, <Outlet / đánh dấu vị trí nội dung con hiện ra. Đường dẫn của route con là tương đối — không phải lặp lại path của route…
- Protected routes trong React Router được implement như thế nào?
Tạo một component bọc, kiểm tra auth rồi redirect nếu chưa đăng nhập: Truyền state={{ from: location }} để sau khi đăng nhập xong còn đưa user về đúng trang họ định vào. <Navigate replace là bản thay thế cho <Redirect của React Router v5.
- Multiple contexts trong một app được tổ chức như thế nào?
Tổ chức nhiều context bằng cách: tạo nhiều Provider riêng biệt, nest chúng lại (thứ tự từ ngoài vào trong), hoặc tạo AppProviders component bọc tất cả providers. Mỗi context chịu trách nhiệm một concern (AuthContext, ThemeContext, CartContext). Tránh god context chứa tất cả global…
- Context re-render optimization là gì?
- React Router SearchParams (query strings) được xử lý như thế nào?
Dùng useSearchParams hook: const [searchParams, setSearchParams] = useSearchParams(). Đọc: searchParams.get('tab'). Cập nhật: setSearchParams({ tab: 'new' }) hay setSearchParams(prev = { prev.set('tab', 'new'); return prev; }). Phù hợp cho filter, pagination state cần share qua URL.
- Data loading với React Router v6.4+ loader functions là gì?
- Uncontrolled component và useRef trong form là gì?
Uncontrolled component lưu giá trị trong DOM, không sync với React state. Dùng ref để đọc khi cần (submit): const inputRef = useRef(null); <input ref={inputRef} /. Kể từ React 19, useRef yêu cầu truyền giá trị khởi tạo (thường là null cho DOM refs). Đơn…
- Formik là gì và tại sao sử dụng nó?
Formik là thư viện quản lý form state, validation, và submission trong React. Xử lý: touched/dirty states, error messages, submission handling, field-level và form-level validation. Giảm boilerplate code đáng kể so với quản lý state thủ công. Tích hợp tốt với Yup cho schema validation.
- React Hook Form khác Formik như thế nào?
React Hook Form dùng uncontrolled components và refs thay vì state, nên ít re-renders hơn (performance tốt hơn). API đơn giản hơn với register, handleSubmit, formState. Bundle size nhỏ hơn Formik. Formik dễ học hơn với explicit controlled pattern. RHF được cộng đồng ưa chuộng…
- Form validation trong React được thực hiện như thế nào?
Các cách: - (1) Manual: check trong onChange/onSubmit, lưu errors vào state. - (2) HTML5 built-in: required, minLength, pattern attributes. - (3) Formik + Yup: declarative schema validation. - (4) React Hook Form với resolver (Yup, Zod). Dùng Zod cho type-safe validation kết hợp TypeScript…
- Error Boundary là gì và cách tạo?
Error Boundary là React component bắt JavaScript errors trong component tree con và hiển thị fallback UI thay vì crash toàn app. Chỉ có thể tạo với Class Component implement getDerivedStateFromError (set error state) và componentDidCatch (log error). Thư viện react-error-boundary cung cấp ErrorBoundary component…
- Error Boundary không bắt được lỗi nào?
Error Boundary không bắt: errors trong event handlers (phải try/catch thủ công), async code (setTimeout, Promises), server-side rendering, errors trong chính Error Boundary component. Chỉ bắt errors trong render phase, lifecycle methods, constructors của component tree bên dưới.
- Dynamic form fields (thêm xoá input fields) được implement như thế nào?
Lưu array of field objects trong state. Render với map, mỗi field có unique id làm key. Thêm: setFields(prev = [...prev, { id: uuid(), value: '' }]). Xoá: setFields(prev = prev.filter(f = f.id !== id)). React Hook Form cung cấp useFieldArray hook xử lý pattern…
- Optimistic UI trong form submission là gì?
- Zod integration với React Hook Form như thế nào?
Dùng @hookform/resolvers/zod với zodResolver: const { register, handleSubmit } = useForm({ resolver: zodResolver(schema) }). Define schema: const schema = z.object({ email: z.string().email(), age: z.number().min(18) }). Errors type-safe từ Zod được truyền vào formState.errors. Cách tiếp cận hiện đại nhất cho type-safe forms.
- Server-side form validation vs client-side validation khi nào dùng cái nào?
- React.memo là gì và cách hoạt động?
React.memo là HOC memoize function component, skip re-render nếu props không thay đổi (shallow comparison). Nên dùng khi component render expensive và props ít thay đổi. Cần kết hợp với useCallback cho function props để có hiệu quả.
- React.lazy và Suspense dùng để làm gì?
React.lazy cho phép lazy load component, chỉ download JavaScript khi component cần render. Suspense hiển thị fallback UI trong khi component đang load. Giúp code splitting, giảm initial bundle size.
- React Fiber là gì?
- Render props pattern là gì?
Render props là technique chia sẻ code giữa components dùng prop là function trả về React element. Component nhận function prop gọi nó với internal state/logic: <Mouse render={({ x, y }) = <Cat x={x} y={y} /} /. Linh hoạt hơn HOC vì tránh naming collisions.…
- Reconciliation algorithm trong React hoạt động như thế nào?
- Windowing/virtualization trong React là gì?
Virtualization chỉ render items hiện trong viewport, không render toàn bộ danh sách hàng nghìn items. Thư viện: react-window (lightweight), react-virtualized (feature-rich). Giảm DOM nodes từ hàng nghìn xuống chỉ ~20-50. Cần thiết khi render danh sách lớn (100 items) gây performance issues.
- Tại sao không nên tạo component trong component (inline components)?
Định nghĩa component bên trong component khác tạo new component type mỗi render, React unmount/remount thay vì update, gây mất state và performance issues. Luôn khai báo components ở top-level module, hoặc ngoài parent component. Nếu cần data từ parent, truyền qua props hoặc dùng…
- Suspense for data fetching hoạt động như thế nào?
- Key prop dùng để reset component state như thế nào?
Thay đổi key của component khiến React unmount component cũ và mount component mới hoàn toàn, reset tất cả state. Kỹ thuật hữu ích để: reset form sau submit <Form key={formKey} /, reset uncontrolled component khi data source thay đổi. Đây là cách React thiết…
- React Server Components khác Client Components như thế nào?
- Tại sao gọi `setCount(count + 1)` ba lần trong cùng event chỉ tăng 1? Khi nào bắt buộc dùng functional updater?
- Tại sao test React component phải wrap trong `act()`? Khi nào RTL tự wrap, khi nào cần `waitFor`/`findBy`?
- React Profiler API đo gì? Giải thích `actualDuration`, `baseDuration`, `commitTime` và cách phát hiện component chậm.
- React dùng event delegation với synthetic events. Tại sao React 17 đổi attach listener từ `document` sang root container?
- React Portal render component ở DOM khác (outside parent), nhưng event vẫn bubble qua React tree. Giải thích cơ chế này.
- useMemo và useCallback khác nhau thế nào? Cho ví dụ thực tế?
useMemo cache kết quả tính toán: useMemo(() = expensiveCalc(data), [data]). useCallback cache function reference: useCallback(() = handleClick(id), [id]). useCallback dùng khi truyền callback xuống child component dùng React.memo. Lạm dụng 2 hooks này có thể giảm performance do overhead.
- useEffect cleanup function chạy khi nào? Tại sao quan trọng?
Cleanup chạy: (1) trước mỗi lần effect re-run khi dependencies thay đổi, (2) khi component unmount. Quan trọng để tránh memory leaks: huỷ subscriptions, abort fetch requests, clear timers. Ví dụ: return () = controller.abort() trong fetch effect.
- Custom hooks là gì? Viết custom hook useFetch đơn giản?
Custom hooks là functions bắt đầu bằng use, tái sử dụng logic stateful giữa components.
- React.memo dùng khi nào? Khi nào KHÔNG nên dùng?
Dùng khi component nhận props ổn định, render tốn kém, và parent re-render thường xuyên mà props không đổi. KHÔNG dùng khi: component luôn nhận props mới (objects/arrays tạo mới), component render nhẹ, hoặc dùng inline callbacks (làm memo mất tác dụng).
- Tại sao không nên tạo object/array mới trong JSX props?
<Child style={{color: 'red'}}/ tạo object mới mỗi render → Child luôn re-render dù dùng React.memo. Fix: khai báo object ngoài component hoặc useMemo. Tương tự với onClick={() = handle(id)} → dùng useCallback hoặc data attribute.
- Error Boundaries hoạt động thế nào? Hạn chế gì?
- Cấu trúc folder React project thường tổ chức thế nào?
Cách tổ chức phổ biến và hiệu quả nhất là theo feature-based, trong đó mỗi tính năng có folder riêng như src/features/auth/ hay src/features/dashboard/, bên trong chứa đầy đủ components, hooks, services, và types của tính năng đó. Phần dùng chung được đặt ở src/components/…
- Giải thích React Server Components vs Client Components?
- Component re-render liên tục, làm sao debug và fix?
Continuous re-render thường do reference instability hoặc missing dependency — dùng DevTools Profiler để identify. - React DevTools Profiler: tìm component render nhiều. - Nguyên nhân phổ biến: tạo object/array mới trong render, missing dependency array useEffect, context value thay đổi. - Fix: React.memo, useMemo/useCallback,…
- Request bị gửi hai lần — làm sao biết là do Strict Mode hay do effect thật sự chạy lại?
Phân biệt bằng ba dấu hiệu: chỉ xảy ra ở môi trường phát triển, mỗi lần mount sinh thêm đúng một lần chạy, và biến mất khi bỏ <StrictMode ra. Nếu thiếu bất kỳ dấu hiệu nào thì nguyên nhân nằm ở chỗ khác. Cách…
- State update nhưng UI không re-render, nguyên nhân?
(1) Mutate object/array trực tiếp thay vì tạo copy mới (React dùng reference comparison). (2) State nằm trong stale closure. (3) Dùng ref thay vì state. Fix: setState([...arr]) hoặc setState({...obj, key: value}) tạo reference mới. Immer giúp tránh lỗi này.
- Memory leak trong React component, cách phát hiện và fix?
Phát hiện: Chrome DevTools tab Memory, so sánh các heap snapshot. Nguyên nhân thường gặp: 1. Quên cleanup subscription/timer trong useEffect. 2. Event listener không được remove. 3. Fetch không được huỷ bằng AbortController. Cách sửa: luôn return cleanup function từ useEffect.
- Trang load chậm, approach debug từ đầu?
Khi trang web load chậm, cần debug có hệ thống từ tổng quan đến chi tiết. Bước đầu tiên mở Chrome DevTools tab Network để xem waterfall — tìm các file quá lớn, requests bị blocking, hoặc API response chậm. Tiếp theo chạy Lighthouse audit…
- Form phức tạp (20+ fields), cách tổ chức state hiệu quả?
Với form nhiều fields, giải pháp phù hợp nhất là dùng React Hook Form vì nó hoạt động theo cơ chế uncontrolled components, chỉ re-render field nào thay đổi thay vì toàn bộ form — performance tốt hơn đáng kể so với controlled approach. Kết…
- Dự án cũ dùng Class Components, chiến lược migrate sang Hooks?
- Thiết kế authentication flow cho SPA (React)?
- i18n (đa ngôn ngữ) là gì? Triển khai multi-language trong React project thế nào?
- CORS error khi gọi API, cách xử lý?
CORS (Cross-Origin Resource Sharing) là cơ chế bảo mật của browser ngăn chặn frontend gọi API từ domain khác nếu server không cho phép — ví dụ app chạy ở localhost:3000 gọi API ở localhost:8080 sẽ bị chặn. Cách fix đúng là backend thêm header…
- SSR/SSG content khác client-side, hydration mismatch?
Hydration mismatch xảy ra khi HTML render từ server khác với kết quả render lần đầu trên client, khiến React báo warning và có thể gây lỗi UI. Nguyên nhân phổ biến nhất là dùng browser-only APIs như window hay localStorage trong quá trình server…
- Optimize React app cho 10,000+ items trong danh sách?
- Khi nào nên dùng useCallback vs useMemo trong React? Cho ví dụ cụ thể từ dự án thực tế.
useCallback dùng để giữ nguyên reference của một function qua các lần render, thường dùng khi truyền callback xuống child component đã được bọc React.memo() để tránh re-render không cần thiết. useMemo dùng để cache lại giá trị tính toán nặng, ví dụ như filtered…
- Giải thích lỗi 'missing dependency' trong useEffect. Tại sao phải thêm dependency array? Khi nào không cần?
React cảnh báo 'missing dependency' khi bạn sử dụng một biến bên trong useEffect nhưng không khai báo nó trong dependency array, vì lúc đó effect sẽ dùng giá trị cũ do stale closure. Nếu không truyền dependency array, effect sẽ chạy sau mỗi lần…
- Làm sao xử lý race condition trong async useEffect?
**Ví dụ:** user type vào search box rồi xoá hết, request cũ về trước request mới.
Race condition xảy ra khi nhiều request bất đồng bộ được gửi đi và response trả về không đúng thứ tự, khiến UI hiển thị dữ liệu sai. Cách xử lý phổ biến nhất là dùng AbortController trong cleanup function của useEffect: tạo controller, truyền…
- Sự khác biệt giữa controlled vs uncontrolled component trong React form. Nên dùng cái nào?
Controlled component là component mà giá trị input được quản lý bởi React state thông qua value và onChange — cho phép kiểm soát hoàn toàn dữ liệu và validate real-time. Uncontrolled component dùng ref để lấy giá trị trực tiếp từ DOM khi cần,…
- Prop drilling là gì? Làm sao giải quyết vấn đề này trong dự án lớn?
Prop drilling là tình trạng phải truyền props qua nhiều tầng component trung gian, dù những component đó không thực sự sử dụng props đó — chỉ đóng vai trò chuyển tiếp. Điều này làm code khó bảo trì và khó refactor. Giải pháp phổ…
- Tại sao list rendering cần key prop? Sử dụng index làm key có vấn đề gì?
Key prop giúp React nhận diện phần tử nào đã thay đổi, được thêm mới, hoặc bị xoá trong danh sách để cập nhật DOM hiệu quả thông qua thuật toán reconciliation. Dùng index làm key sẽ gây lỗi nghiêm trọng khi danh sách bị…
- Lazy loading & code splitting trong React. Khi nào cần? Cách implement?
Lazy loading là kỹ thuật chỉ tải component khi thực sự cần thiết, giúp giảm kích thước bundle ban đầu và tăng tốc trang. Cách implement: dùng React.lazy() kết hợp Suspense, ví dụ const Dashboard = lazy(() = import('./Dashboard')) rồi bọc trong <Suspense fallback={<Loading /}.…
- Cách optimize infinite scroll list. Giải thích virtual scrolling concept.
Virtual scrolling là kỹ thuật chỉ render những item đang hiển thị trong viewport, còn những item ngoài tầm nhìn sẽ bị loại khỏi DOM. Nhờ vậy dù danh sách có hàng chục ngàn item, trình duyệt chỉ cần xử lý vài chục DOM node…
- Explain React.memo() & memo() hook. Khi nào nên dùng?
React.memo() là higher-order component bọc quanh functional component để bỏ qua re-render nếu props không thay đổi, so sánh bằng shallow comparison. Nên dùng khi: child component có chi phí render cao, parent re-render thường xuyên mà props của child ít thay đổi. Cần lưu…
- Custom Hook pattern. Viết custom hook để manage form state. Testing?
Custom Hook là cách trích xuất logic tái sử dụng từ component thành function riêng, tên bắt đầu bằng 'use'. Ví dụ useForm(initialValues) trả về {values, handleChange, reset, errors} để quản lý state và validation của form. Để test custom hook, dùng renderHook từ @testing-library/react-hooks…
- Error boundary trong React. Cách implement, use case?
Error boundary là component đặc biệt dùng để bắt lỗi JavaScript trong cây component con, ngăn không cho toàn bộ ứng dụng bị crash trắng màn hình. Cách implement: tạo class component với method componentDidCatch và static getDerivedStateFromError, khi có lỗi sẽ hiển thị fallback…
- Compound component pattern. Tại sao hữu ích? Implement example?
Compound component là pattern trong đó component cha quản lý state nội bộ và chia sẻ cho các component con thông qua Context, tạo nên một nhóm component hoạt động cùng nhau. Ví dụ: <Tabs là cha quản lý tab đang active, <Tab và <TabPanel…
- Render prop vs HOC pattern. Modern React dùng gì?
Render prop là pattern component nhận một function làm prop (hoặc children) và gọi function đó với dữ liệu cần thiết để render UI. HOC (Higher-Order Component) là function nhận một component và trả về component mới đã được bổ sung logic. Cả hai đều…
- Suspense trong React. Fallback, error boundary, data fetching?
Suspense là cơ chế cho phép React tạm dừng render một component và hiển thị fallback UI (ví dụ loading spinner) cho đến khi component đó sẵn sàng. Hiện tại Suspense hoạt động tốt nhất với React.lazy() cho lazy loading component và với các framework…
- So sánh Redux Toolkit, Zustand, Jotai và Context API — khi nào nên chọn cái nào để quản lý state?
Bốn lựa chọn giải quyết các nhu cầu khác nhau, đừng mặc định reach for Redux. - Context API: không phải state manager, chỉ là cơ chế truyền value tránh prop drilling (theme, locale, user đã đăng nhập). Mọi consumer re-render khi value đổi →…
- Làm thế nào để viết component React accessible (a11y)? Vai trò của semantic HTML, ARIA, focus management và useId là gì?
Accessibility không phải tính năng thêm, mà là cách build mặc định. - Semantic HTML trước tiên: dùng <button, <nav, <main, <label thay vì <div onClick. Native element có sẵn role, keyboard handling, focus — ARIA chỉ để vá khi không có element phù hợp.…
- Cách type props của component với TypeScript dùng generics và discriminated-union? Giải thích khi nào cần mỗi cái.
- Cách type event handler và ref trong React với TypeScript? Lấy đúng kiểu event và element ở đâu?
Vấn đề thường gặp là khai báo kiểu any cho event hoặc đoán sai kiểu element. Event handlers — React có sẵn type generic theo element và loại event. Lấy đúng kiểu thay vì any: Mẹo: khai báo handler inline trên JSX prop thì TS…
- Test component với React Testing Library nên theo nguyên tắc nào? Thứ tự ưu tiên query, vai trò của user-event và vì sao tránh test implementation details?
Triết lý RTL: "test như cách người dùng dùng app", không test nội bộ. Thứ tự ưu tiên query (từ tốt nhất xuống): 1. Accessible — getByRole (kèm name), getByLabelText, getByPlaceholderText, getByText. Phản ánh đúng cách user và screen reader nhìn UI. 2. Semantic —…
- Error Boundary và thư viện react-error-boundary giải quyết gì? Vì sao hook (try/catch trong component) không bắt được lỗi render?
Error Boundary là class component bắt lỗi trong lúc render của cây con, hiển thị fallback UI thay vì sập cả app (React unmount toàn bộ tree nếu lỗi không được bắt). Nó bắt qua static getDerivedStateFromError (cập nhật state để render fallback) và componentDidCatch…
- useTransition và useDeferredValue khác nhau như thế nào? Khi nào dùng cái nào để giữ UI mượt khi cập nhật nặng?
- React Compiler (React 19) là gì và nó tự động memo hoá những gì? Còn cần useMemo/useCallback/React.memo nữa không?
- Custom Hook là gì và tại sao chúng ta nên sử dụng nó?
Custom Hook là một hàm JavaScript thông thường, nhưng tên của nó bắt đầu bằng use và bên trong có thể gọi các Hook khác của React (như useState, useEffect, useContext, v.v.). Tại sao nên sử dụng Custom Hook? - Tái sử dụng Logic: Tách…
- Lint `react-hooks/exhaustive-deps` báo thiếu dependency. Thêm `// eslint-disable-next-line` để tắt cảnh báo có sao không?
Không nên. Cảnh báo đó nói rằng effect đọc một giá trị reactive (prop, state, hoặc biến tính từ chúng) nhưng không khai báo trong dependency array — nghĩa là khi giá trị đó đổi, effect không chạy lại và tiếp tục dùng giá trị…
- Khi nào lưu giá trị vào `useRef` thay vì `useState`? Cho ví dụ thực tế.
Quy tắc phân biệt: giá trị nào hiển thị ra UI thì dùng state; giá trị chỉ để ghi nhớ giữa các lần render thì dùng ref. useState useRef --------- Gán giá trị mới gọi setter, gây re-render gán ref.current, không re-render Đọc trong render…
- `useId` sinh ra để làm gì? Vì sao không tự sinh id bằng `Math.random()` hay biến đếm toàn cục?
useId tạo một chuỗi id duy nhất và ổn định để nối <label htmlFor với <input id, hoặc để gắn aria-describedby, aria-labelledby. Vì sao không tự sinh: - Math.random() cho giá trị khác nhau giữa server và client → hydration mismatch, React cảnh báo và…
- Gọi `setState` sau khi component đã unmount có gây memory leak không? Có cần cờ `isMounted` trong effect không?
Không cần cờ isMounted. Cảnh báo "Can't perform a React state update on an unmounted component" đã được gỡ khỏi React 18 vì nó báo nhầm nhiều hơn báo đúng: gọi setter trên component đã unmount chỉ là no-op, bản thân nó không rò bộ…
- Đồng hồ đếm dùng `setInterval` trong `useEffect` với deps `[]` bị đứng ở 1. Nguyên nhân và các cách sửa?
Callback truyền cho setInterval được tạo ở lần render đầu tiên và giữ nguyên mãi. Nó capture biến count của render đó — luôn là 0 — nên mỗi giây đều tính 0 + 1. Ba hướng sửa, chọn theo nhu cầu: 1. Functional updater…
- Component con nhận `onMessage` từ cha và gọi trong `useEffect` đăng ký WebSocket. Thêm `onMessage` vào deps thì kết nối bị mở lại liên tục, bỏ ra thì lint kêu. Xử lý thế nào?
Đây là dấu hiệu effect đang trộn hai loại logic: phần reactive (kết nối lại khi roomId đổi) và phần không reactive (gọi callback mới nhất khi có tin nhắn). Cha tạo onMessage mới mỗi render nên deps đổi liên tục. Các hướng xử lý…
- Khi nào logic thuộc về event handler chứ không phải `useEffect`? Cho ví dụ hay sai trong dự án.
Nguyên tắc: effect dùng để đồng bộ với hệ thống bên ngoài (WebSocket, DOM API, analytics của bên thứ ba theo vòng đời màn hình). Việc xảy ra vì người dùng làm gì đó thuộc về event handler. Mẫu sai hay gặp — gửi đơn…
- Màn hình đang giữ `loading`, `error`, `data` bằng ba `useState` riêng và thỉnh thoảng rơi vào trạng thái vô lý (vừa loading vừa có error). Bạn xử lý thế nào?
Vấn đề là cấu trúc state cho phép biểu diễn trạng thái không thể xảy ra. Ba boolean/giá trị độc lập tạo ra tổ hợp mà UI không định nghĩa, và mỗi handler phải nhớ reset đủ cả ba — chỉ cần quên một chỗ…
- Team đang dùng custom hook `useFetch` tự viết. Vì sao nhiều dự án chuyển sang React Query/SWR? Tự viết khó đúng ở chỗ nào?
Một useFetch gọn gàng chỉ giải quyết phần dễ nhất: gọi API rồi set state. Phần khó nằm ở những thứ đến sau khi tính năng lớn lên: - Race condition: hai request cùng key về không đúng thứ tự, kết quả cũ ghi đè…
- Tooltip đo chiều cao rồi tự lật lên trên bị nhấp nháy một khung hình. Dùng `useLayoutEffect` sửa được, nhưng SSR lại cảnh báo. Giải thích và xử lý.
useEffect chạy sau khi trình duyệt đã vẽ, nên người dùng kịp thấy một khung hình tooltip ở vị trí sai rồi mới nhảy. useLayoutEffect chạy sau khi DOM được cập nhật nhưng trước khi vẽ, nên việc đo và chỉnh vị trí gộp vào…
- Effect chạy hai lần ở môi trường dev khiến API bị gọi đôi. Đồng nghiệp chặn bằng `useRef` cờ `didRun`. Bạn nhận xét thế nào?
Cách chặn bằng cờ ref chỉ giấu triệu chứng. Trong StrictMode ở dev, React cố tình mount → unmount → mount lại và chạy setup/cleanup hai lượt để phát hiện effect thiếu cleanup. Bản build production chỉ chạy một lần. Điều nó phơi ra: effect…
- React 19 cho phép nhận `ref` như một prop thường. `forwardRef` và `useImperativeHandle` giờ dùng ra sao?
- Đọc `localStorage` hoặc `matchMedia` bằng `useState` + `useEffect` gặp vấn đề gì? `useSyncExternalStore` khắc phục ra sao?
- Khi dependency của effect ở cả cha và con cùng đổi, thứ tự chạy cleanup và setup là gì? Vì sao thứ tự đó quan trọng?
- Sau khi `setState` thêm dòng vào danh sách, bạn muốn đọc `scrollHeight` để cuộn xuống cuối nhưng đọc ra giá trị cũ. `flushSync` giải quyết gì và vì sao nên hạn chế dùng?
- Vì sao không được gọi hook trong `if` hay vòng lặp? Bên trong React hỏng cụ thể ở đâu?
- Một component React re-render trong những trường hợp nào?
Có đúng ba nguồn kích hoạt: 1. State của chính nó thay đổi — gọi setter và giá trị mới khác giá trị cũ (so sánh bằng Object.is). 2. Component cha render lại — mặc định mọi component con render theo, kể cả khi props…
- Re-render có đồng nghĩa với việc DOM bị cập nhật không? Phân biệt render phase và commit phase.
Không. Một lần cập nhật đi qua hai giai đoạn tách biệt: - Render phase — React gọi hàm component, thu được cây element mới, rồi so sánh với cây trước đó. Giai đoạn này chỉ tính toán, không chạm DOM, có thể bị React…
- Dùng index của mảng làm `key` sai ở chỗ nào? Khi nào thì vẫn chấp nhận được?
key là định danh của item giữa hai lần render — React dùng nó để quyết định giữ hay huỷ state và DOM node của phần tử. Index chỉ là vị trí, nên khi danh sách thay đổi thứ tự, định danh bị gán nhầm.…
- Truyền arrow function inline như `onClick={() => save(id)}` có làm chậm ứng dụng không?
Với DOM element thì gần như không. Tạo một closure là thao tác rất rẻ, và React gắn listener theo cơ chế delegation nên không phải add/remove listener mỗi lần render. Vấn đề chỉ xuất hiện khi hàm đó là prop của một component đã…
- Đã bọc `React.memo` nhưng component vẫn render lại mỗi lần. Bạn kiểm tra những gì?
memo chỉ bỏ qua render khi mọi prop đều bằng nhau theo so sánh nông (Object.is từng prop). Danh sách kiểm tra theo thứ tự hay gặp: 1. Prop là tham chiếu mới mỗi lần — object/array/function literal, style={{...}}, data={rows.filter(...)}. Đây là nguyên nhân số…
- Giải thích kỹ thuật truyền phần nặng qua `children` để tránh re-render, không cần `memo`.
Ý tưởng: element được tạo ở chỗ viết JSX, chứ không phải chỗ render nó. Nếu component nặng do một component ở tầng trên tạo ra (không có state hay thay đổi), thì component đang thay đổi state chỉ nhận nó dưới dạng prop children…
- Vì sao bọc `memo` không ngăn được re-render do context? Cách tách context cho app lớn.
- Automatic batching trong React 18 hoạt động ra sao? Khi nào bắt buộc phải dùng `flushSync` và cái giá của nó?
- Set state bằng đúng giá trị hiện tại thì React có render lại không?
- Giá trị dẫn xuất (filter, tổng tiền, danh sách đã sắp xếp) nên tính trong render, lưu vào state, hay bọc `useMemo`?
- Concurrent rendering trong React 18 nghĩa là gì? Nói "render có thể bị ngắt" là ngắt cái gì?
Trước React 18, một lần render là đồng bộ và không thể dừng: React bắt đầu dựng cây component thì phải chạy hết mới trả quyền điều khiển lại cho trình duyệt. Cây lớn thì main thread bị chiếm, gõ phím hoặc click bị trễ.…
- Chia code bằng `React.lazy` + `Suspense`, mỗi lần chuyển tab fallback nhấp nháy một cái rồi biến mất. Vì sao và xử lý thế nào?
Nhấp nháy vì chunk tải rất nhanh (vài chục ms): React kịp hiện fallback rồi thay ngay bằng nội dung thật, mắt người đọc thành một cú giật. Các cách xử lý, theo thứ tự nên thử: 1. Đánh dấu chuyển tab là transition. Trong…
- React 19 cho render `<title>`, `<meta>`, `<link>` ngay trong component. Nó hoạt động ra sao và có thay được `react-helmet` không?
Từ React 19, khi component render một thẻ <title, <meta hoặc <link, React tự động đưa thẻ đó lên <head của trang, kể cả khi component nằm sâu trong cây. Điểm cần biết: - Hoạt động cả khi render phía server (thẻ nằm sẵn trong…
- `useFormStatus` dùng để làm gì? Vì sao nút submit phải nằm trong component con của `<form>` mới đọc được trạng thái?
useFormStatus cho một component đọc trạng thái gửi của form cha gần nhất mà không cần truyền prop isSubmitting xuống. Nó đọc trạng thái qua Context do chính thẻ <form cung cấp, mà Context chỉ truyền xuống dưới. Nếu gọi useFormStatus ngay trong ContactForm —…
- Ô tìm kiếm lọc bảng 5.000 dòng bị khựng khi gõ. Bạn chọn `useTransition` hay `useDeferredValue`? Khác nhau ở đâu?
Cả hai đều hạ ưu tiên phần render nặng để ô input phản hồi ngay. Khác nhau ở chỗ bạn nắm được gì. useTransition — dùng khi bạn tự gọi được setState: useDeferredValue — dùng khi giá trị đến từ props hoặc nơi khác, bạn…
- `useDeferredValue` khác gì debounce? Đã có `useDebounce` tự viết rồi thì cần nó nữa không?
Debounce hoãn theo đồng hồ; useDeferredValue hoãn theo mức bận của máy. debounce 300ms useDeferredValue --------- Điều kiện chạy hết 300ms không gõ thêm React rảnh sau khi xong việc gấp Máy khoẻ vẫn chờ đủ 300ms cập nhật gần như ngay Máy yếu vẫn…
- Hook `use()` của React 19 khác các hook khác thế nào? Vì sao được phép gọi trong `if` mà `useState` thì không?
use() đọc giá trị từ một resource — hiện hỗ trợ Promise và Context. Vì sao gọi trong if được: các hook như useState phải gọi cố định thứ tự vì React lưu state trong một danh sách theo vị trí gọi — nhảy cóc…
- Trang chi tiết dùng Suspense nhưng vẫn tải chậm vì các request xếp hàng nối đuôi. Waterfall xảy ra ở đâu và sửa thế nào?
Waterfall xảy ra khi request sau chỉ bắt đầu sau khi request trước xong, dù chúng độc lập với nhau. Với Suspense, nguyên nhân phổ biến là component con chỉ được render (và mới bắt đầu fetch) sau khi component cha đã có dữ liệu.…
- Nút "Thích" cần đổi màu ngay khi bấm dù request chưa xong. Dùng `useOptimistic` thế nào, và khi request lỗi thì trạng thái quay lại ra sao?
useOptimistic cho bạn một bản sao tạm của state để hiển thị trong lúc một action đang chạy. Rollback là tự động và đó là điểm hay bị hỏi: giá trị optimistic chỉ tồn tại trong phạm vi transition/action đang chạy. Khi action kết thúc…
- Suspense và Error Boundary phối hợp thế nào? Khi fetch trong Suspense bị lỗi thì ai bắt, và làm sao cho người dùng thử lại?
Chia vai rõ: Suspense bắt trạng thái "chưa có dữ liệu" (promise pending), Error Boundary bắt trạng thái "hỏng" (promise reject hoặc lỗi khi render). Một promise bị reject sẽ đi xuyên qua Suspense và dừng ở Error Boundary gần nhất phía trên. Đặt Error…
- Console báo "Hydration failed / text content does not match". Nguyên nhân hay gặp và cách sửa từng loại?
Hydration mismatch nghĩa là HTML server sinh ra khác với cây React client dựng ở lần render đầu. React 18 trở đi sẽ vứt HTML của vùng đó và render lại từ client, kèm cảnh báo — kết quả là chậm và có thể nhấp…
- Selective hydration trong React 18 là gì? Người dùng click vào vùng chưa hydrate thì chuyện gì xảy ra?
- Streaming SSR khác `renderToString` ra sao? Giải thích `renderToPipeableStream` và khác biệt giữa `onShellReady` và `onAllReady`.
- React Compiler tự memo hoá thì có còn cần `useMemo`, `useCallback`, `React.memo` không? Nó thay đổi cách viết code ở đâu?
- React 19 cho callback ref trả về hàm cleanup. Trước đó dọn dẹp thế nào, và thay đổi này gây breaking change gì?
- Actions trong React 19 là gì? Thiết kế form submit bằng `useActionState` khác gì so với tự quản lý `loading`/`error` bằng `useState`?
- Fetch dữ liệu trong Server Component khác gì `useEffect` + `fetch` ở client?
Trong Server Component, component là hàm async và await trực tiếp — dữ liệu đã có sẵn khi HTML được sinh ra. Khác biệt chính so với useEffect: - Số round-trip mạng: client cần tải HTML → tải JS → hydrate → mới gọi API…
- Trang có một truy vấn chậm 3 giây làm cả trang trắng. Dùng Suspense để stream như thế nào?
Nguyên nhân: await ở ngay thân page.tsx chặn toàn bộ output — server không gửi được byte nào cho tới khi truy vấn xong. Cách sửa: đẩy phần chậm xuống component con và bọc <Suspense. Phần nhanh được stream ngay, phần chậm gửi bổ sung…
- Sau khi mutation thành công, khi nào dùng `invalidateQueries` và khi nào dùng `setQueryData`?
invalidateQueries đánh dấu cache là stale và refetch các query đang active — dữ liệu chắc chắn đúng vì lấy lại từ server, nhưng tốn thêm một round-trip. setQueryData ghi thẳng kết quả mutation vào cache — không tốn request nào, nhưng bạn phải tự…
- Backend báo số request tăng đột biến sau khi dùng React Query: mỗi lần chuyển tab trình duyệt là API bị gọi lại. Bạn chẩn đoán và cấu hình thế nào?
- Optimistic update trong React Query: vì sao phải gọi `cancelQueries` trước khi ghi cache, và rollback đúng cách ra sao?
- Với `useInfiniteQuery`, làm sao cập nhật một item vừa sửa mà không phải fetch lại toàn bộ các trang đã tải?
- Chặn route theo quyền (role/permission) ở frontend bạn làm thế nào?
Đặt một lớp guard giữa router và page, và luôn nhớ đây chỉ là lớp trải nghiệm — quyền thật do server quyết định. Mô hình thường dùng: session chứa danh sách permissions, mỗi route khai báo quyền nó cần, guard so khớp. Ba điểm…
- Danh sách infinite scroll: bấm vào một item rồi bấm Back, làm sao giữ đúng vị trí và số trang đã tải?
- Form đăng ký nhiều bước có lưu nháp: bạn tổ chức state và validate thế nào?
Nguyên tắc: một nguồn dữ liệu duy nhất cho cả wizard, mỗi bước chỉ hiển thị một phần của nó. State. Giữ toàn bộ giá trị ở form cha (FormProvider của react-hook-form, hoặc một reducer), mỗi bước đọc/ghi qua context. Nếu mỗi bước tự giữ…
- Form động cho phép thêm/xoá dòng (ví dụ danh sách sản phẩm trong đơn hàng) — bạn xử lý state và validate thế nào?
Mô hình chuẩn là một mảng object trong form state, mỗi dòng là một phần tử; validate bằng schema mảng để lỗi bám đúng chỉ số dòng. Lỗi thường gặp là dùng key={i}. Khi xoá dòng giữa, React coi các dòng sau là "cùng key,…
- Bảng dữ liệu lớn có filter, sort và phân trang phía server: bạn thiết kế state và luồng gọi API thế nào?
- Ô tìm kiếm gợi ý (autocomplete): làm sao để kết quả cũ không ghi đè kết quả mới và bàn phím dùng được?
Ba lớp cần xử lý: giảm số request, chống kết quả về sai thứ tự, điều khiển bằng bàn phím. Giảm request. Debounce khoảng 250–300ms và bỏ qua chuỗi quá ngắn (< 2 ký tự). Nếu có cache theo từ khoá thì gõ lại từ…
- Nút Like / Thêm giỏ hàng: bạn làm optimistic UI thế nào khi người dùng bấm liên tục nhiều lần?
- Một màn hình lấy dữ liệu cần thể hiện những trạng thái nào? Bạn hiển thị loading / empty / error ra sao?
Tối thiểu bốn trạng thái: đang tải, có dữ liệu, rỗng, lỗi. Bỏ sót trạng thái rỗng là lỗi hay gặp nhất — danh sách không có dữ liệu trông y hệt lỗi im lặng. Cách trình bày từng trạng thái: - Loading: dùng skeleton…
- Làm sao đổi ngôn ngữ VI/EN ngay lập tức mà không cần reload trang?
Đưa ngôn ngữ hiện tại thành state của ứng dụng chứ không phải biến đọc một lần lúc khởi động. Khi state đổi, React render lại và mọi chuỗi được lấy lại từ từ điển. Những điểm cần nói thêm: - Không hardcode chuỗi trong…