Base.vn Prep

2026-05-19 · Middle-level

DRILL RESULT

Knowledge Check — Mon 5/18 14:30

Top 28 Drill Q rapid-fire (~25 min) · Coverage: BE Async · FE/React · TanStack · Forms · BE Deep · 4 rounds × 7 câu

Final Score

65%

🟡 Middle band

🔴 Red zone

5

Top weak spots

🟡 Yellow zone

5

Secondary

✅ Strong

10

Đã vững

📊 Score by Round

Round Topic Score Status
1BE Async (Q1-7)66%🟡 OK
2FE / React (Q8-14)63%🟡 OK
3TanStack / Forms (Q15-20)55%🟠 Cần củng cố
4BE Deep (Q21-28)78%🟢 Tốt
Total28 questions~65%🟡 Middle

65% = đủ qua middle-level interview với điều kiện catch trên các câu generic. Fix 5 weak spots trước Tue 5/19 để bump lên 80%+.

🔴 TOP 5 Weak Spots — drill kỹ trước interview

#1 · Q2 — Promise Combinators

SAI · KHÔNG NHỚ

Câu cực dễ hỏi · Phải nhớ bảng 4 method

MethodFail behaviorUse case
Promise.allFirst reject → throw NGAYAll MUST succeed (3 API call render page)
Promise.allSettledNEVER throws, wait allCollect partial (gửi 100 email, OK 1-2 fail)
Promise.raceFirst settle wins (resolve OR reject)Implement timeout
Promise.anyAll fail → AggregateErrorTry multiple, take fastest SUCCESS

Mnemonic: all = fail-fast · allSettled = wait-everyone · race = first-finish · any = first-success

#2 · Q21 — PUT vs PATCH idempotent (FLIPPED)

NGƯỢC

Bạn trả lời "PATCH idempotent". SAI — ngược lại.

VerbBodyIdempotent?
PUTFull resource (replace)Yes theo RFC 7231
PATCHPartial fields⚠️ Depends · thường yes, vd PATCH {amount: "+1"} KHÔNG idempotent

Phrase: "PUT replace toàn bộ resource, idempotent theo spec. PATCH partial update, spec nói depends — set value cụ thể thì idempotent, delta thì không."

#3 · Q18 — Optimistic Update 4 callback (MISS onSettled)

THIẾU STEP

Bạn quên onSettled invalidate. Đây là step 4 quan trọng để sync với server.

useMutation({
  mutationFn: api.likeTask,

  onMutate: async (id) => {                            // 1️⃣ TRƯỚC mutationFn
    await qc.cancelQueries(['task', id]);              //   1a. CANCEL
    const previous = qc.getQueryData(['task', id]);    //   1b. SNAPSHOT
    qc.setQueryData(['task', id], { ...previous, liked: true });  // 1c. SET optimistic
    return { previous };
  },
  onError: (_, id, ctx) => {                           // 2️⃣ nếu fail
    qc.setQueryData(['task', id], ctx.previous);       //   ROLLBACK
  },
  onSettled: (_, __, id) => {                          // 3️⃣ luôn chạy (success/error)
    qc.invalidateQueries(['task', id]);                //   INVALIDATE → refetch
  },
});

Memorize: onMutate (cancel + snapshot + set) → onError (rollback) → onSettled (invalidate). 4 step trong 3 callback.

#4 · Q14 — AbortController vs Cleanup Flag

CONFUSED

Bạn nói "cleanup dọn cả component" — SAI. Cleanup flag KHÔNG dọn component.

PatternCancel network?Skip setState?
AbortController✅ Browser dừng gửi/nhận✅ Auto (fetch throw AbortError)
Cleanup flag (isMounted = false)❌ Request vẫn gửi + server vẫn process✅ Manual if (isMounted) setState(...)

Phrase: "AbortController CANCEL request thật — tiết kiệm bandwidth + server resource. Cleanup flag chỉ skip setState — request vẫn waste. AbortController luôn tốt hơn."

→ Card chi tiết: frontend.html#abort

#5 · Q11 — Hook Rules WHY (call order)

KHÔNG NHỚ LÝ DO

Bạn nhớ rules nhưng quên WHY. Interviewer hay đào sâu chỗ này.

  1. Only at top level — KHÔNG trong if / for / while / nested function / event handler
  2. Only in components or custom hooks — KHÔNG trong utility function thường. Custom hook CÓ THỂ gọi hook khác.

WHY (interview-critical):

React track hooks bằng CALL ORDER. Mỗi render React expect hooks gọi theo cùng thứ tự. Nếu conditional / loop → order thay đổi giữa các render → state mapping sai → crash. Linter react-hooks/rules-of-hooks enforce.

Phrase: "2 rules: top level only, components/hooks only. React match state bằng call order — conditional → order khác → state map sai → crash."

🟡 Secondary Weak Spots

Q16 · staleTime default = 0 (KHÔNG phải 30s)

Default 0 → data luôn stale → refetch on mount/window focus. gcTime = 5 phút (đúng). gcTime đếm từ khi observer cuối cùng unmount, không phải khi stale.

Q24/25 · Refresh token ở cookie httpOnly, KHÔNG memory

Storage chuẩn 2026: Access in-memory (JS variable) · Refresh in cookie httpOnly + Secure + SameSite=Strict. SessionStorage CÒN sau F5 (cùng tab), không phải "mất khi F5" — nhược điểm thật của sessionStorage = vẫn JS-accessible → vẫn XSS-able.

Q13/Q20 · RHF dùng ref (uncontrolled) + mode: 'onTouched' + useWatch

RHF uncontrolled bên trong → ít re-render. Per-field subscription validate realtime được như controlled. Password checklist: tách sub-component dùng useWatch để chỉ re-render checklist khi password đổi, KHÔNG re-render form parent.

Q28 · Multi-tenancy default = Pattern 1 (tenant_id column)

Default pick: Shared schema + tenantId column. Lý do: cost thấp, scale tốt, migration đơn giản. Mitigate leak: Prisma middleware auto-inject WHERE tenant_id HOẶC Postgres RLS. Composite UNIQUE: UNIQUE(tenant_id, email).

Q4 · 3 cách fix race condition là ALTERNATIVES, không phải chain

Chọn 1 trong 3: (1) Atomic UPDATE single-statement · (2) SELECT FOR UPDATE explicit lock · (3) Optimistic locking với version + retry. Không phải "Update → For Update → version" tuần tự.

✅ Strong Areas — đã vững

📋 Study Plan — slot 15:00-16:00 (1h)

15:00-15:20

Re-read 5 weak spots trên site

15:20-15:40

Đọc to Top 28 Drill

Mở phase-3.html#drill · đọc từng câu + answer 1-line · tốc độ 30s/câu

15:40-16:00

Self-test 5 weak spot không nhìn

Mở notepad / Notion · gõ lại answer cho Q2 (Promise combinator table), Q11 (Hook rules WHY), Q14 (AbortController vs flag table), Q18 (Optimistic 4 callback code), Q21 (PUT vs PATCH table). Sau đó so sánh với card trên site.

16:00 →

Sang Phase 4 · Base.vn Research

Đi tới phase-4.html · Part A research 16:00-18:00 · Part B STAR stories 18:00-20:00

📚 Full 28 Q&A Correction Sheet

Click expand từng round để xem answer chuẩn. Dùng làm reference cho slot 15:40 self-test.

Round 1 · BE Async (Q1-7) · Score 66%
Q1 · Node concurrent? Event loop schedule callbacks + libuv thread pool (default 4) handle I/O. JS single-thread, I/O delegate → concurrent.
Q2 · Promise combinators? all fail-fast · allSettled wait-everyone · race first-finish · any first-success.
Q3 · POST /pay 2 lần? Header Idempotency-Key (UUID v4) + table idempotency_log(key PK, result JSONB, request_hash, created_at) TTL 24h. SELECT trước, có thì trả cached.
Q4 · UPDATE race? Có. 3 ALTERNATIVES: (1) atomic UPDATE single-statement · (2) SELECT FOR UPDATE · (3) optimistic locking với version + retry.
Q5 · CPU-bound? Worker threads.
Q6 · 10GB CSV? Streams + pipeline + backpressure (auto-handle).
Q7 · Trace? 1, 4, 3, 2. Sync trước → drain microtask (Promise.then) → drain macrotask (setTimeout).
Round 2 · FE / React (Q8-14) · Score 63%
Q8 · useEffect race? AbortController (cancel old request) + có thể combine debounce (giảm spam). AbortController fix root cause.
Q9 · setCount stale closure? setCount(prev => prev + 1) functional update.
Q10 · Spam API? Debounce 300-500ms.
Q11 · Hook rules? (1) Top level only (2) Components/hooks only. WHY: React match state bằng call order.
Q12 · useMemo default? Không. 3 case: expensive calc · reference identity cho memoized child · tránh useEffect re-run vô tận.
Q13 · Controlled vs Uncontrolled? Controlled = React state (mỗi keystroke re-render). Uncontrolled = DOM giữ value (ít re-render). RHF = uncontrolled với ref + per-field subscription.
Q14 · AbortController vs cleanup flag? AbortController CANCEL network thật. Cleanup flag chỉ skip setState — request vẫn waste. AbortController luôn tốt hơn.
Round 3 · TanStack / Forms (Q15-20) · Score 55%
Q15 · isPending vs isFetching? isPending = chưa có data cache (first load) → full skeleton. isFetching = đang fetch (kể cả background) → subtle indicator.
Q16 · staleTime vs gcTime defaults? staleTime = 0 · gcTime = 5 phút. gcTime đếm từ khi observer cuối unmount.
Q17 · meta option? Arbitrary object KHÔNG affect cache. Global handlers đọc → custom error message, invalidation by tag, analytics, conditional toast.
Q18 · Optimistic 4 callback? onMutate (cancel + snapshot + set) → onError (rollback) → onSettled (invalidate).
Q19 · Form 100 fields? RHF / TanStack Form + Zod + shadcn/MUI Form + tabs/stepper UX + useWatch cho dependent field.
Q20 · Password validate? Zod .min(8).refine(...) chain + RHF mode: 'onTouched' + checklist tách sub-component dùng useWatch.
Round 4 · BE Deep (Q21-28) · Score 78%
Q21 · PUT vs PATCH idempotent? PUT idempotent theo spec. PATCH "depends" — set value yes, delta no.
Q22 · POST success? 201 Created + Location header trỏ resource mới.
Q23 · 401 vs 403? 401 = chưa login / token invalid. 403 = đã login nhưng không có quyền (RBAC fail).
Q24 · Tại sao 2 token? Access short-lived (15min) limit blast radius khi leak. Refresh long-lived (7-30d) trong cookie httpOnly → renew không bắt re-login.
Q25 · JWT storage? Access in-memory (JS variable). Refresh in cookie httpOnly + Secure + SameSite=Strict. Bootstrap flow on reload.
Q26 · Prisma N+1? Phát hiện qua query log. Fix bằng include / select. GraphQL dùng DataLoader batch.
Q27 · Batch vs Interactive? Batch (array) khi op độc lập. Interactive (callback) khi có logic phụ thuộc — throw để rollback.
Q28 · Multi-tenancy default? Pattern 1 — Shared schema + tenant_id. Cost thấp, scale tốt. Mitigate leak: Prisma middleware HOẶC Postgres RLS.