Việc làm

10/09 · Hồ Chí Minh · Tại văn phòng

ReactJS Developer

VOYAGER INC · Frontend Developer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

10 câu hỏi có thể gặp khi phỏng vấn

Chọn theo kỹ năng và cấp của tin (ReactJS, DevOps & CI/CD, JavaScript & TypeScript). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.

  1. 01React render và cập nhật DOM thế nào? Vì sao list cần key và không nên dùng index làm key?ReactJS · Junior

    Gợi ý trả lời

    Mỗi lần state hoặc props đổi, React gọi lại component để tạo cây element mới, so sánh với cây cũ (reconciliation), rồi chỉ cập nhật phần DOM thật sự thay đổi.

    • Với list, key cho React biết phần tử nào là phần tử nào giữa hai lần render. Key phải ổn định và duy nhất trong list, thường là id từ dữ liệu.
    • Dùng index làm key chỉ ổn khi list không bao giờ chèn, xoá hay đổi thứ tự.

    Hay sai: dùng index cho list có thể xoá hoặc sắp xếp. React ghép nhầm state của item cũ sang item mới: ô input giữ nội dung của dòng đã bị xoá, checkbox tick sai dòng.

    Mẹo hay được hỏi thêm: đổi key của một component là cách chủ động reset toàn bộ state của nó.

    Ôn thêm câu hỏi ReactJS →
  2. 02Props và state khác nhau thế nào? Vì sao không được sửa trực tiếp state?ReactJS · Junior

    Gợi ý trả lời

    Props là dữ liệu cha truyền xuống, component con chỉ đọc. State là dữ liệu component tự quản lý; đổi state sẽ khiến component render lại.

    • React so sánh state cũ và mới bằng tham chiếu (Object.is). Sửa trực tiếp state.items.push(x) thì tham chiếu không đổi, React có thể không render lại, và các tối ưu như memo cũng hỏng.
    • Luôn tạo object hoặc array mới:
    setItems(prev => [...prev, newItem]);
    setUser(prev => ({ ...prev, name: "An" }));
    
    • setState không cập nhật biến ngay trong lần render hiện tại. React gom nhiều lần set lại (batching) rồi mới render.

    Hay sai: gọi setCount(count + 1) ba lần liên tiếp và mong tăng 3. Kết quả chỉ tăng 1; muốn tăng 3 phải dùng dạng hàm setCount(c => c + 1).

    Ôn thêm câu hỏi ReactJS →
  3. 03useEffect dùng để làm gì? Dependency array và hàm cleanup hoạt động ra sao?ReactJS · Junior

    Gợi ý trả lời

    useEffect dùng để đồng bộ component với hệ thống bên ngoài: subscribe sự kiện, kết nối WebSocket, gọi thư viện không phải React, gọi API.

    • Không có dependency array: chạy sau mỗi lần render.
    • []: chạy sau lần mount đầu tiên.
    • [a, b]: chạy lại khi a hoặc b đổi.
    • Hàm return là cleanup, chạy trước lần effect kế tiếp và khi unmount.
    useEffect(() => {
      const id = setInterval(tick, 1000);
      return () => clearInterval(id);
    }, []);
    

    Ở development, Strict Mode cố ý chạy effect hai lần để bạn phát hiện thiếu cleanup.

    Hay sai: dùng effect để tính dữ liệu dẫn xuất từ state/props (setFullName(first + last)). Hãy tính thẳng trong lúc render; effect thừa gây render hai lần và dễ lệch dữ liệu.

    Ôn thêm câu hỏi ReactJS →
  4. 04Bạn viết Dockerfile thế nào để image nhỏ, build nhanh và an toàn?DevOps & CI/CD · Junior

    Gợi ý trả lời

    Ý chính: dùng multi-stage build, sắp xếp layer để tận dụng cache, và không chạy bằng root.

    FROM node:22-alpine AS build
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    FROM node:22-alpine
    USER node
    COPY --from=build /app/dist /app
    
    • Copy file khai báo dependency trước, code sau, để đổi code không phải cài lại package.
    • Dùng .dockerignore loại node_modules, .git, file .env.
    • Không nhét secret vào image (kể cả ở layer đã xoá); dùng build secret hoặc biến môi trường lúc chạy.
    • Ghim phiên bản base image, quét lỗ hổng trong pipeline.
    Ôn thêm câu hỏi DevOps & CI/CD →
  5. 05CI, Continuous Delivery và Continuous Deployment khác nhau thế nào? Một pipeline cơ bản gồm những bước gì?DevOps & CI/CD · Junior

    Gợi ý trả lời

    CI là tự động build và test mỗi lần merge code; Continuous Delivery là luôn có bản sẵn sàng deploy nhưng lên production cần bấm duyệt; Continuous Deployment thì tự lên production nếu mọi bước đều qua.

    Pipeline cơ bản:

    • Checkout, cài dependency (có cache).
    • Lint, unit test, quét bảo mật (SAST, dependency, secret).
    • Build artifact/image, gắn tag theo commit SHA, đẩy lên registry.
    • Deploy lên staging, chạy smoke/integration test.
    • Deploy production (thủ công hoặc tự động), có cách rollback.

    Người phỏng vấn muốn nghe: build một lần, dùng cùng một artifact cho mọi môi trường; chỉ cấu hình là khác nhau.

    Ôn thêm câu hỏi DevOps & CI/CD →
  6. 06Closure là gì? Giải thích kết quả của vòng lặp for (var i...) với setTimeout.JavaScript & TypeScript · Junior

    Gợi ý trả lời

    Closure là khi một hàm "nhớ" được các biến ở phạm vi nơi nó được tạo ra, kể cả sau khi hàm bên ngoài đã chạy xong.

    for (var i = 0; i < 3; i++) {
      setTimeout(() => console.log(i), 0);
    }
    // In ra 3, 3, 3
    
    • var chỉ có một biến i cho cả vòng lặp. Khi callback chạy, vòng lặp đã xong và i bằng 3.
    • Đổi sang let thì mỗi vòng lặp có một i riêng, in ra 0, 1, 2.

    Ứng dụng thực tế: tạo biến private, hàm factory, debounce, memoize, và các hook trong React.

    Hay sai: closure giữ tham chiếu đến biến chứ không chụp lại giá trị. Closure giữ object lớn quá lâu (ví dụ trong listener không gỡ) cũng là nguồn rò rỉ bộ nhớ.

    Ôn thêm câu hỏi JavaScript & TypeScript →
  7. 07Controlled component và uncontrolled component khác nhau thế nào? Khi nào dùng loại nào?ReactJS · Junior

    Gợi ý trả lời

    Controlled: giá trị input nằm trong state React, mọi thay đổi đi qua onChange. Uncontrolled: DOM tự giữ giá trị, bạn đọc khi cần qua ref hoặc khi form submit.

    <input value={name} onChange={e => setName(e.target.value)} />
    <input defaultValue="An" name="name" />
    
    • Controlled hợp khi cần validate ngay khi gõ, định dạng giá trị, hoặc ô này phụ thuộc ô kia.
    • Uncontrolled đơn giản hơn, ít render hơn; hợp với form lớn hoặc khi dùng thư viện như React Hook Form. React 19 còn hỗ trợ truyền hàm vào <form action> và đọc dữ liệu bằng FormData.

    Hay sai: chuyển một input từ value={undefined} sang có giá trị, khiến React cảnh báo đổi từ uncontrolled sang controlled. Khởi tạo state bằng "" thay vì undefined.

    Ôn thêm câu hỏi ReactJS →
  8. 08Khi nào nên dùng useMemo, useCallback và React.memo? Dùng tràn lan có sao không?ReactJS

    Gợi ý trả lời

    Cả ba dùng để tránh tính toán hoặc render lại không cần thiết:

    • useMemo: nhớ kết quả của phép tính tốn kém.
    • useCallback: nhớ hàm, để tham chiếu không đổi giữa các lần render.
    • React.memo: bỏ qua render component con nếu props không đổi (so sánh nông).

    Chúng thường phải đi cùng nhau: truyền hàm mới mỗi lần render vào component đã memo thì memo vô tác dụng.

    Dùng tràn lan làm code khó đọc, tốn công so sánh dependency, và dễ sai khi thiếu dependency. Chỉ nên dùng khi đã đo bằng React DevTools Profiler và thấy chậm, hoặc khi giá trị đó là dependency của effect.

    React Compiler có thể tự thêm memo khi build, giảm nhu cầu viết tay.

    Người phỏng vấn muốn nghe: trước khi memo, hãy thử đưa state xuống thấp hơn hoặc truyền component qua children để giảm phạm vi render lại.

    Ôn thêm câu hỏi ReactJS →
  9. 09Custom hook là gì? Các quy tắc của hooks là gì và vì sao có chúng?ReactJS

    Gợi ý trả lời

    Custom hook là hàm bắt đầu bằng use, dùng các hook khác bên trong, để tái sử dụng logic có state giữa nhiều component (không chia sẻ state, mỗi component có bản riêng).

    function useDebounce(value, ms) {
      const [debounced, setDebounced] = useState(value);
      useEffect(() => {
        const id = setTimeout(() => setDebounced(value), ms);
        return () => clearTimeout(id);
      }, [value, ms]);
      return debounced;
    }
    

    Quy tắc: chỉ gọi hook ở cấp cao nhất của component hoặc custom hook; không gọi trong if, vòng lặp hay sau return sớm. Lý do: React nhận diện từng hook theo thứ tự gọi, đổi thứ tự là state bị ghép nhầm.

    Ngoại lệ: hook use() của React 19 được gọi trong điều kiện.

    Người phỏng vấn muốn nghe: bạn bật ESLint plugin react-hooks để bắt các lỗi này tự động.

    Ôn thêm câu hỏi ReactJS →
  10. 10Kể về một thất bại hoặc sai lầm của bạn và bài học rút ra.Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Chọn sai lầm thật, có hậu quả vừa phải, nhận trách nhiệm rõ ràng, và nhấn mạnh việc bạn đã thay đổi sau đó.

    Cấu trúc: chuyện gì xảy ra, phần lỗi của bạn, bạn khắc phục ngay thế nào, bài học và thay đổi lâu dài.

    Câu mẫu: "Có lần em deploy một thay đổi cấu hình lên production vào chiều thứ Sáu mà không kiểm tra kỹ trên staging, làm một tính năng lỗi khoảng một giờ. Em báo ngay cho lead, rollback và viết báo cáo sự cố. Sau đó em đề xuất checklist trước deploy và quy ước hạn chế deploy cuối tuần; team áp dụng tới giờ."

    Hay sai: kể một "thất bại" thực ra là khoe, đổ lỗi cho người khác, hoặc nói mình chưa từng thất bại.

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở VOYAGER INC?

Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.

Chia sẻ kinh nghiệm phỏng vấn