Top 116 câu hỏi phỏng vấn React.js

01

Làm thế nào để comment trong React?

Trong React, việc thêm comment vào mã JSX có thể hơi khác so với cách bạn thường thêm comment trong HTML hoặc JavaScript thuần túy. Điều này là do JSX là một cú pháp mở rộng cho JavaScript, được xử lý bởi Babel trước khi chuyển thành mã JavaScript mà trình duyệt có thể hiểu. Dưới đây là cách để thêm comment trong React:

Comment trong JSX

Để thêm comment trong JSX, bạn sử dụng cú pháp của comment trong JavaScript nhưng phải đặt nó bên trong dấu ngoặc nhọn {} vì JSX là JavaScript. Điều này cho phép bạn chèn một biểu thức JavaScript - trong trường hợp này là một comment - vào trong JSX.

jsx
function MyComponent() {
  return (
    <div>
      {/* Đây là comment trong JSX */}
      <h1>Hello, World!</h1>
    </div>
  );
}

Comment trong nhiều dòng

Nếu bạn muốn comment nhiều dòng trong JSX, bạn vẫn sử dụng cùng một cú pháp nhưng mở rộng nó ra nhiều dòng.

jsx
function MyComponent() {
  return (
    <div>
      {/*
        Đây là comment nhiều dòng
        trong JSX.
      */}
      <h1>Hello, World!</h1>
    </div>
  );
}

Comment bên ngoài JSX

Nếu bạn đang viết comment bên ngoài phần trả về của JSX, bạn có thể sử dụng comment JavaScript thông thường mà không cần dấu ngoặc nhọn.

jsx
// Đây là comment bên ngoài JSX
function MyComponent() {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  );
}

Lưu ý

  • Khi thêm comment trong JSX, hãy chắc chắn rằng bạn đặt comment bên trong dấu ngoặc nhọn {}.
  • Comment không xuất hiện trong DOM sau khi ứng dụng được render.
  • Sử dụng comment một cách hợp lý để giải thích logic hoặc để làm rõ mã nguồn, nhưng tránh làm rối mã nguồn với quá nhiều comment.

Việc sử dụng comment một cách hiệu quả có thể giúp làm cho mã nguồn của bạn dễ đọc và bảo trì hơn.

02

ReactJS là gì? Nêu các tính năng nổi bật của Reactjs?

ReactJS, thường được gọi đơn giản là React, là một thư viện JavaScript mã nguồn mở được phát triển bởi Facebook (nay là Meta) để xây dựng giao diện người dùng (UI) động và hiệu quả cho các ứng dụng web và di động. React được giới thiệu vào năm 2013 và nhanh chóng trở thành một trong những công nghệ phát triển giao diện phổ biến nhất, được sử dụng bởi nhiều công ty lớn và dự án trên toàn thế giới.

Các tính năng nổi bật của ReactJS

1. Component-Based Architecture

ReactJS sử dụng kiến trúc dựa trên component, nghĩa là giao diện người dùng được chia thành các phần nhỏ, độc lập gọi là components. Mỗi component có thể quản lý trạng thái (state) của nó và được tái sử dụng trong ứng dụng, giúp việc phát triển ứng dụng trở nên dễ dàng và hiệu quả hơn.

2. Virtual DOM

React sử dụng Virtual DOM để tối ưu hóa hiệu suất bằng cách giảm thiểu số lượng cập nhật DOM thực tế. Khi trạng thái của một component thay đổi, React sẽ tạo ra một Virtual DOM tree mới và so sánh nó với phiên bản trước đó để xác định những thay đổi cần được thực hiện trên DOM thực tế. Điều này giúp tăng tốc độ và hiệu suất của ứng dụng.

3. One-Way Data Binding

React thực hiện một chiều dữ liệu ràng buộc (one-way data binding), nghĩa là dữ liệu trong ứng dụng chỉ di chuyển theo một hướng từ parent components xuống child components thông qua props. Điều này giúp kiểm soát và theo dõi dòng dữ liệu trong ứng dụng dễ dàng hơn, giảm thiểu lỗi và tăng khả năng bảo trì.

4. JSX

JSX là một cú pháp mở rộng cho JavaScript cho phép viết XML/HTML trong mã JavaScript. Sử dụng JSX giúp mã nguồn dễ đọc và viết hơn, đồng thời cho phép React hiển thị thông tin từ mã JavaScript dễ dàng hơn thông qua cú pháp giống như template.

5. React Native

React Native là một framework được xây dựng dựa trên React, cho phép phát triển ứng dụng di động chéo nền tảng (cross-platform) với hiệu suất gần như ứng dụng native. React Native sử dụng cùng một kiến trúc component và cho phép chia sẻ code giữa ứng dụng web và di động, giúp tối ưu hóa quá trình phát triển.

6. Cộng đồng lớn và hỗ trợ mạnh mẽ

React có một cộng đồng lớn và đang phát triển mạnh mẽ với hàng nghìn nhà phát triển và công ty đóng góp. Điều này đảm bảo rằng React sẽ tiếp tục được cải thiện và hỗ trợ trong tương lai, cũng như có sẵn một lượng lớn tài nguyên học tập và thư viện bên thứ ba.

ReactJS đã trở thành một công cụ không thể thiếu trong bộ công cụ của các nhà phát triển front-end, nhờ vào sự linh hoạt, hiệu suất cao và cộng đồng hỗ trợ mạnh mẽ.

03

useState() trong React là gì?

useState() là một Hook trong React cho phép bạn thêm trạng thái (state) React vào trong functional components. Trước khi Hooks được giới thiệu trong React 16.8, trạng thái chỉ có thể được sử dụng trong class components. useState() cung cấp một cách để lưu trữ và quản lý dữ liệu địa phương trong một component mà không cần chuyển đổi nó thành một class component.

Cách Sử Dụng useState()

useState() nhận một giá trị khởi tạo và trả về một mảng với hai phần tử: giá trị hiện tại của trạng thái và một hàm để cập nhật trạng thái đó. Bạn có thể sử dụng giá trị này trong component của mình và gọi hàm cập nhật khi bạn muốn thay đổi trạng thái.

Ví dụ:

jsx
import React, { useState } from 'react';

function Counter() {
  // Khai báo một biến trạng thái mới, gọi là "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Bạn đã click {count} lần</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Trong ví dụ trên, useState(0) khởi tạo trạng thái với giá trị ban đầu là 0. Biến count được sử dụng để hiển thị giá trị hiện tại của trạng thái, và hàm setCount được sử dụng để cập nhật giá trị của count.

Lưu Ý Khi Sử Dụng useState()

  • Hàm cập nhật trạng thái (setCount trong ví dụ trên) không tự động gộp hoặc kết hợp các cập nhật. Để cập nhật trạng thái dựa trên giá trị hiện tại, bạn nên sử dụng một hàm nhận giá trị hiện tại của trạng thái và trả về giá trị mới.
  • useState() không tự động gộp các cập nhật trạng thái như this.setState trong class components. Mỗi lần gọi useState() tạo ra một trạng thái và hàm cập nhật riêng biệt cho trạng thái đó.
  • Bạn có thể sử dụng nhiều hook useState() trong một component để quản lý nhiều biến trạng thái.

useState() là một phần cơ bản của việc sử dụng Hooks trong React, giúp việc quản lý trạng thái trong functional components trở nên dễ dàng và linh hoạt hơn.

04

DOM ảo là gì?

DOM ảo (Virtual DOM) là một khái niệm quan trọng trong phát triển ứng dụng web hiện đại, đặc biệt là trong các thư viện và framework như React. Virtual DOM là một bản sao nhẹ của DOM thực tế (Real DOM) và được sử dụng như một lớp trung gian giữa trạng thái của ứng dụng và trạng thái được hiển thị trên giao diện người dùng.

Cách hoạt động của Virtual DOM

  1. Cập nhật: Khi trạng thái của ứng dụng thay đổi, thay vì cập nhật trực tiếp trên Real DOM, một bản sao mới của Virtual DOM sẽ được tạo ra và phản ánh những thay đổi đó.
  2. So sánh: Virtual DOM mới sẽ được so sánh với bản sao trước đó của Virtual DOM để xác định những thay đổi cụ thể nào cần được thực hiện trên Real DOM.
  3. Cập nhật Real DOM: Chỉ những thay đổi cần thiết được xác định từ bước so sánh sẽ được áp dụng lên Real DOM, giúp tối ưu hóa hiệu suất bằng cách giảm thiểu số lượng tương tác với Real DOM.

Lợi ích của Virtual DOM

  • Hiệu suất cao: Việc sử dụng Virtual DOM giúp giảm thiểu số lượng cập nhật trực tiếp trên Real DOM, từ đó cải thiện hiệu suất ứng dụng do Real DOM thao tác chậm và tốn kém về mặt tài nguyên.
  • Khả năng phản hồi nhanh: Ứng dụng có thể cập nhật giao diện người dùng một cách nhanh chóng mà không làm giảm hiệu suất, mang lại trải nghiệm người dùng mượt mà hơn.
  • Tính linh hoạt: Virtual DOM cung cấp một lớp trừu tượng hóa cho phép các nhà phát triển không cần phải lo lắng về cách thức tối ưu hóa các thao tác DOM, giúp họ tập trung vào logic ứng dụng.

Kết luận

Virtual DOM là một kỹ thuật hiệu quả giúp tối ưu hóa việc cập nhật giao diện người dùng trong các ứng dụng web phức tạp. Bằng cách giảm thiểu số lượng tương tác trực tiếp với Real DOM, Virtual DOM giúp cải thiện đáng kể hiệu suất và trải nghiệm người dùng, đồng thời cung cấp một mô hình phát triển ứng dụng linh hoạt và hiệu quả.

05

React hook là gì?

React Hook là một tính năng được giới thiệu trong React 16.8, cho phép bạn sử dụng state và các tính năng React khác mà không cần phải viết một class. Hooks là các hàm cho phép bạn "kết nối" vào các tính năng lifecycle và state của React từ các function components. Trước khi có Hooks, các function components được coi là stateless components và không thể sử dụng các tính năng như state hay lifecycle methods. Hooks đã thay đổi điều này, mang lại khả năng sử dụng rộng rãi hơn cho function components và giúp viết ứng dụng React trở nên dễ dàng và gọn gàng hơn.

Các Loại Hook Cơ Bản

  1. useState: Cho phép bạn thêm state vào function components.

    javascript
    const [count, setCount] = useState(0);
  2. useEffect: Cho phép bạn thực hiện các side effect trong function components. Nó tương tự như componentDidMount, componentDidUpdate, và componentWillUnmount trong class components.

    javascript
    useEffect(() => {
      document.title = `You clicked ${count} times`;
    });
  3. useContext: Cho phép bạn truy cập vào context và dữ liệu từ context provider mà không cần sử dụng consumer.

    javascript
    const value = useContext(MyContext);

Tại sao lại sử dụng Hooks?

  • Sự đơn giản: Hooks giúp bạn viết các components với logic tái sử dụng mà không cần phải tách ra thành nhiều class khác nhau.
  • Tái sử dụng logic không tăng kích thước component: Trước đây, việc tái sử dụng stateful logic giữa các components thường yêu cầu các patterns như higher-order components hoặc render props. Hooks cho phép bạn tái sử dụng stateful logic mà không thay đổi cấu trúc component của bạn.
  • Tổ chức logic liên quan: Hooks cho phép bạn sắp xếp logic liên quan vào một nơi mà không phải phân chia theo lifecycle methods.
  • Sử dụng các tính năng React mà không cần classes: Hooks giúp bạn sử dụng nhiều tính năng React mà không cần định nghĩa một class.

Kết luận

React Hooks mang lại một cách tiếp cận mới và mạnh mẽ để xây dựng các components trong React, giúp việc quản lý state và lifecycle trở nên dễ dàng và linh hoạt hơn. Bằng cách sử dụng Hooks, các nhà phát triển có thể viết code gọn gàng và dễ bảo trì hơn, đồng thời tận dụng được sức mạnh của React mà không cần phải dựa vào class components.

06

State trong React là gì?

State trong Reactjs là một đối tượng JavaScript được sử dụng để lưu trữ thông tin về trạng thái của một component. State có thể thay đổi theo thời gian, thường do sự kiện người dùng hoặc hệ thống, và mỗi khi state thay đổi, React sẽ tự động thực hiện việc re-render component để cập nhật giao diện người dùng phản ánh trạng thái mới.

Đặc điểm của State:

  • Động: State cho phép React components thay đổi output của chúng theo thời gian phản ứng với hành động người dùng, phản hồi mạng, và bất kỳ sự kiện nào khác.
  • Tư nhân: State được quản lý trong component và không thể truy cập trực tiếp từ bên ngoài component đó. Điều này giúp tạo ra các ứng dụng có cấu trúc và dễ quản lý hơn.
  • Cập nhật: Để cập nhật state, bạn sử dụng phương thức setState() trong class components hoặc hook useState() trong function components. React sẽ lên lịch một cập nhật cho component khi state thay đổi.

Ví dụ về State:

Trong class component:

javascript
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  incrementCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

Trong function component với hook useState:

javascript
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementCount}>Increment</button>
    </div>
  );
}

Trong cả hai ví dụ trên, count là một phần của state của component Counter. Khi nút "Increment" được nhấn, hàm incrementCount được gọi, cập nhật state, và gây ra việc re-render component với giá trị count mới.

Tóm lại, state là một phần cốt lõi của React giúp tạo ra các ứng dụng động và tương tác, cho phép các component phản ứng với dữ liệu đầu vào và thay đổi theo thời gian.

07

React Hooks là gì?

React Hooks là một tính năng được giới thiệu trong React 16.8, cho phép bạn sử dụng state và các tính năng React khác mà không cần phải viết một class. Hooks là các hàm cho phép bạn "kết nối" vào các tính năng lifecycle và state của React từ các function components. Trước khi có Hooks, các function components được coi là stateless components và không thể sử dụng các tính năng như state hay lifecycle methods. Hooks đã thay đổi điều này, mang lại khả năng sử dụng rộng rãi hơn cho function components và giúp viết ứng dụng React trở nên dễ dàng và gọn gàng hơn.

Các Loại Hook Cơ Bản

  1. useState: Cho phép bạn thêm state vào function components.

    javascript
    const [count, setCount] = useState(0);
  2. useEffect: Cho phép bạn thực hiện các side effect trong function components. Nó tương tự như componentDidMount, componentDidUpdate, và componentWillUnmount trong class components.

    javascript
    useEffect(() => {
      document.title = `You clicked ${count} times`;
    });
  3. useContext: Cho phép bạn truy cập vào context và dữ liệu từ context provider mà không cần sử dụng consumer.

    javascript
    const value = useContext(MyContext);

Tại sao lại sử dụng Hooks?

  • Sự đơn giản: Hooks giúp bạn viết các components với logic tái sử dụng mà không cần phải tách ra thành nhiều class khác nhau.
  • Tái sử dụng logic không tăng kích thước component: Trước đây, việc tái sử dụng stateful logic giữa các components thường yêu cầu các patterns như higher-order components hoặc render props. Hooks cho phép bạn tái sử dụng stateful logic mà không thay đổi cấu trúc component của bạn.
  • Tổ chức logic liên quan: Hooks cho phép bạn sắp xếp logic liên quan vào một nơi mà không phải phân chia theo lifecycle methods.
  • Sử dụng các tính năng React mà không cần classes: Hooks giúp bạn sử dụng nhiều tính năng React mà không cần định nghĩa một class.

Tóm lại, React Hooks mang lại một cách tiếp cận mới và mạnh mẽ để xây dựng các components trong React, giúp việc quản lý state và lifecycle trở nên dễ dàng và linh hoạt hơn. Bằng cách sử dụng Hooks, các nhà phát triển có thể viết code gọn gàng và dễ bảo trì hơn, đồng thời tận dụng được sức mạnh của React mà không cần phải dựa vào class components.

08

JSX là gì? Trình duyệt có đọc được JSX không?

JSX là một cú pháp mở rộng của JavaScript được sử dụng trong React để mô tả cấu trúc giao diện người dùng. JSX cung cấp một cách để viết các thành phần UI giống như HTML trong mã JavaScript, giúp việc phát triển giao diện trở nên trực quan và dễ hiểu hơn. Mặc dù JSX trông giống HTML, nhưng thực chất nó là một cú pháp đặc biệt mà React sử dụng để tạo ra các đối tượng React Element.

Các trình duyệt có đọc được JSX không?

Các trình duyệt web không thể hiểu trực tiếp JSX vì nó không phải là một phần của tiêu chuẩn JavaScript. Để sử dụng JSX trong các ứng dụng web, mã JSX cần được "biên dịch" thành JavaScript thông thường mà trình duyệt có thể hiểu được. Quá trình biên dịch này thường được thực hiện bằng các công cụ như Babel, một trình biên dịch JavaScript hiện đại có thể chuyển đổi JSX thành các lệnh gọi hàm React.createElement() trước khi mã được chạy trong trình duyệt.

Ví dụ, đoạn mã JSX sau:

jsx
const element = <h1>Hello, world!</h1>;

sẽ được Babel biên dịch thành:

javascript
const element = React.createElement('h1', null, 'Hello, world!');

Sau khi biên dịch, mã JavaScript kết quả có thể được thực thi bởi trình duyệt mà không gặp vấn đề gì.

09

Sự khác nhau giữa stateprops trong React là gì?

Trong React, stateprops là hai khái niệm cốt lõi giúp quản lý dữ liệu và tương tác trong các component. Dưới đây là sự khác biệt chính giữa stateprops:

State

  • Định nghĩa: state là một tập hợp các dữ liệu động mà component có thể sở hữu và quản lý. State có thể thay đổi theo thời gian, thường do sự kiện người dùng hoặc hệ thống.
  • Quản lý: state được quản lý bên trong component và có thể được cập nhật bằng cách sử dụng this.setState() trong class components hoặc hooks như useState trong function components.
  • Tính riêng tư: state là riêng tư và chỉ có thể truy cập hoặc thay đổi bởi chính component đó.
  • Khi sử dụng: Sử dụng state khi dữ liệu cần thay đổi theo thời gian hoặc do tương tác người dùng.

Props

  • Định nghĩa: props (viết tắt của "properties") là các tham số mà component nhận từ bên ngoài, thường là từ component cha. Props được sử dụng để truyền dữ liệu và sự kiện giữa các component.
  • Tính bất biến: props là bất biến, tức là một khi đã được truyền vào component, bạn không thể thay đổi giá trị của chúng bên trong component đó.
  • Tính tái sử dụng: props giúp tăng tính tái sử dụng của component bằng cách cho phép component nhận dữ liệu động từ cha, giúp tạo ra các component linh hoạt và tái sử dụng.
  • Khi sử dụng: Sử dụng props khi bạn muốn truyền dữ liệu từ component cha xuống component con hoặc khi bạn muốn render component dựa trên dữ liệu đầu vào từ bên ngoài.

Ví dụ

javascript
class ParentComponent extends React.Component {
  state = {
    greeting: 'Hello'
  };

  render() {
    return <ChildComponent greeting={this.state.greeting} />;
  }
}

class ChildComponent extends React.Component {
  render() {
    // Props được sử dụng ở đây và không thể thay đổi
    return <h1>{this.props.greeting}, World!</h1>;
  }
}

Trong ví dụ trên, ParentComponentstate chứa dữ liệu chào hỏi, và nó truyền state này như một prop cho ChildComponent. ChildComponent sau đó sử dụng prop để render dữ liệu, nhưng không thể thay đổi nó.

Tóm lại, stateprops đều quan trọng trong việc xây dựng các ứng dụng React, nhưng chúng phục vụ cho các mục đích khác nhau: state cho phép component quản lý dữ liệu động của chính mình, trong khi props cho phép truyền dữ liệu giữa các component, tạo ra một dòng dữ liệu một chiều từ component cha xuống component con.

10

Props trong React là gì?

Props trong React là một cơ chế để truyền dữ liệu từ một component cha sang một component con trong ứng dụng React. Props (viết tắt của "properties") là các đối số mà bạn cung cấp cho một component React và chúng là read-only, tức là không thể được thay đổi bởi component nhận props.

Đặc điểm của Props

  • Read-only: Props không thể được thay đổi bởi component nhận chúng. Nếu bạn cần thay đổi dữ liệu, bạn sẽ cần sử dụng state.
  • Truyền dữ liệu: Props cho phép bạn truyền dữ liệu từ component cha xuống component con, giúp tạo ra các component có thể tái sử dụng và tùy chỉnh.
  • Truyền hàm: Ngoài dữ liệu, props cũng có thể được sử dụng để truyền hàm từ component cha xuống component con, cho phép các component con giao tiếp với component cha hoặc thực hiện các hành động khi được kích hoạt.

Ví dụ về Props

jsx
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return <Welcome name="Alice" />;
}

Trong ví dụ trên, component Welcome nhận props và sử dụng nó để hiển thị tên. Component App truyền một prop name với giá trị "Alice" đến component Welcome.

Lợi ích của Props

  • Tái sử dụng component: Props giúp bạn tạo ra các component có thể tái sử dụng với dữ liệu khác nhau mà không cần phải viết lại code.
  • Tổ chức code: Props giúp bạn tổ chức code một cách rõ ràng, với một luồng dữ liệu từ trên xuống dễ theo dõi.
  • Tách biệt logic: Bằng cách sử dụng props, bạn có thể tách biệt logic của component cha và con, giúp code dễ bảo trì và mở rộng hơn.

Tóm lại, props là một phần quan trọng của React, giúp xây dựng các ứng dụng có cấu trúc tốt và dễ quản lý.

11

Component trong Reactjs là gì?

Trong React, một component là một đơn vị độc lập, có thể tái sử dụng, thường đại diện cho một phần của giao diện người dùng (UI). Mỗi component trong React được xây dựng để hoạt động độc lập, cho phép bạn tạo ra các ứng dụng phức tạp bằng cách kết hợp nhiều component nhỏ và tái sử dụng chúng.

Đặc điểm của Component

  • Tái sử dụng: Components được thiết kế để có thể tái sử dụng ở nhiều nơi trong ứng dụng, giúp giảm thiểu việc lặp lại mã nguồn và tăng tính bảo trì.
  • Độc lập: Mỗi component quản lý trạng thái của riêng mình và render UI dựa trên trạng thái đó, giúp tách biệt logic và UI của ứng dụng thành các phần nhỏ, dễ quản lý hơn.
  • Composable: Components có thể được kết hợp với nhau để tạo ra các giao diện phức tạp. Một component có thể sử dụng các component khác trong render method của mình.

Loại Components

Trong React, có hai loại component chính:

  1. Class Components: Được xây dựng sử dụng ES6 class. Class components cho phép sử dụng các tính năng như state và lifecycle methods.

    javascript
    class Welcome extends React.Component {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
      }
    }
  2. Function Components: Được viết dưới dạng các hàm JavaScript. Với sự giới thiệu của Hooks trong React 16.8, function components cũng có thể sử dụng state và các tính năng khác giống như class components.

    javascript
    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }

Sử dụng Components

Components được sử dụng để xây dựng các phần tử UI bằng cách trả về một cây các React elements. Cây này được React sử dụng để xây dựng DOM và cập nhật UI khi dữ liệu thay đổi.

Kết luận

Components là trái tim của bất kỳ ứng dụng React nào, giúp tạo ra các ứng dụng web động và phản hồi nhanh chóng với khả năng tái sử dụng cao và dễ dàng bảo trì. Sự linh hoạt và mạnh mẽ của components làm cho React trở thành một trong những thư viện JavaScript phổ biến nhất cho phát triển giao diện người dùng.

12

ReactDOM là gì?

ReactDOM là một thư viện trong hệ sinh thái React, cung cấp các API cần thiết để gắn kết React components vào DOM (Document Object Model). Nói cách khác, ReactDOM cho phép bạn "mount" (gắn) các components React vào DOM, giúp chúng có thể hiển thị và tương tác với người dùng trong môi trường web.

Chức năng chính của ReactDOM:

ReactDOM.render(): Phương thức này được sử dụng để render một React element hoặc component vào một nút DOM cụ thể trong HTML. Đây là bước cần thiết để biến mã JSX hoặc components thành các phần tử HTML có thể nhìn thấy được trên trình duyệt.

javascript
ReactDOM.render(<App />, document.getElementById('root'));

Trong ví dụ trên, ReactDOM.render sẽ render component App vào nút DOM có idroot.

ReactDOM.createPortal(): Phương thức này cho phép bạn render children vào một nút DOM khác, không phải là nút DOM hiện tại của component. Điều này hữu ích trong các trường hợp như khi bạn muốn render một modal, tooltip, hoặc một toast notification vào một phần khác của DOM để tránh các vấn đề về CSS hoặc z-index.

ReactDOM.unmountComponentAtNode(): Phương thức này được sử dụng để gỡ bỏ một component đã được mount từ DOM. Điều này thường được sử dụng để dọn dẹp khi component không còn cần thiết nữa, giúp tránh rò rỉ bộ nhớ.

ReactDOM.findDOMNode(): Phương thức này (không được khuyến nghị sử dụng trong các phiên bản mới của React) được sử dụng để tìm nút DOM tương ứng với một instance component cụ thể. Tuy nhiên, việc sử dụng phương thức này thường không cần thiết và có thể được thay thế bằng cách sử dụng refs.

Lưu ý:

Trong các phiên bản mới của React, việc sử dụng ReactDOM đã được đơn giản hóa với sự xuất hiện của React 18 và các API mới như createRoothydrateRoot, cung cấp một cách tiếp cận hiệu quả hơn cho việc render và hydrate ứng dụng React.

Tóm lại, ReactDOM là một phần không thể thiếu trong việc sử dụng React để xây dựng ứng dụng web, nó cung cấp cầu nối giữa React components và DOM, cho phép các components có thể hiển thị và hoạt động trong môi trường web.

13

React context là gì?

React Context là một cơ chế trong React cho phép bạn chia sẻ dữ liệu một cách dễ dàng giữa tất cả các component trong cùng một cây component, mà không cần phải truyền props xuống từng cấp một cách thủ công. Context được thiết kế để chia sẻ dữ liệu mà có thể được coi là "toàn cục" cho một cây component, như là thông tin xác thực người dùng hiện tại, theme ứng dụng, hoặc ngôn ngữ ưu tiên.

Cách hoạt động của Context

Để sử dụng Context, bạn sẽ tạo một Context mới bằng cách sử dụng React.createContext() và sau đó sử dụng Provider để bao bọc cây component của bạn. Các component con sau đó có thể đăng ký để lắng nghe thay đổi của Context thông qua Consumer hoặc useContext hook.

Ví dụ về Context

jsx
import React, { createContext, useContext } from 'react';

// Tạo một Context mới
const UserContext = createContext();

function App() {
  // Sử dụng Provider để truyền dữ liệu
  return (
    <UserContext.Provider value="Alice">
      <Header />
    </UserContext.Provider>
  );
}

function Header() {
  // Sử dụng useContext hook để truy cập dữ liệu từ Context
  const user = useContext(UserContext);
  return <h1>Welcome, {user}!</h1>;
}

Trong ví dụ trên, UserContext được tạo ra và sử dụng để truyền tên người dùng "Alice" xuống component Header mà không cần phải truyền qua props.

Lợi ích của Context

  • Tránh "prop drilling": Context giúp bạn tránh việc phải truyền dữ liệu qua nhiều cấp component, một vấn đề thường được gọi là "prop drilling".
  • Dễ dàng quản lý trạng thái toàn cục: Context cung cấp một cách dễ dàng để quản lý và truy cập trạng thái toàn cục trong ứng dụng của bạn.
  • Tối ưu hóa hiệu suất: Khi sử dụng Context, chỉ những component đăng ký lắng nghe Context mới được cập nhật khi có thay đổi, giúp tối ưu hóa hiệu suất ứng dụng.

Tóm lại, React Context là một công cụ hữu ích cho việc quản lý trạng thái toàn cục và chia sẻ dữ liệu giữa các component mà không cần phải truyền props một cách thủ công qua cây component.

14

Ưu điểm của việc sử dụng React Hooks là gì?

React Hooks là một tính năng được giới thiệu trong React 16.8, cho phép bạn sử dụng state và các tính năng React khác mà không cần phải viết một class. Việc sử dụng React Hooks mang lại nhiều ưu điểm:

1. Viết Component Dễ Dàng và Gọn Gàng

  • Sử dụng Function Components: Hooks cho phép bạn sử dụng state và các tính năng phụ trợ khác trong function components, giúp code trở nên gọn gàng và dễ đọc hơn so với class components.
  • Giảm Boilerplate Code: Không cần sử dụng các phương thức vòng đời của class như componentDidMount, componentDidUpdate, và componentWillUnmount, giảm lượng boilerplate code cần thiết.

2. Tái Sử Dụng Logic Một Cách Dễ Dàng

  • Custom Hooks: Cho phép bạn tạo ra các custom hooks riêng, giúp tái sử dụng logic trạng thái và phụ trợ một cách dễ dàng giữa các components.
  • Chia Sẻ Logic Không Liên Quan Đến UI: Hooks giúp chia sẻ logic không liên quan đến UI (ví dụ: đăng ký và hủy đăng ký sự kiện) mà không cần sử dụng các pattern phức tạp như render props hoặc higher-order components.

3. Code Dễ Hiểu và Dễ Bảo Trì

  • Phân Tách Logic Theo Chức Năng: Hooks cho phép bạn tổ chức code theo chức năng thay vì theo vòng đời, giúp code dễ hiểu và dễ bảo trì hơn.
  • Giảm Sự Phụ Thuộc: Giảm sự phụ thuộc giữa các components và làm cho logic ứng dụng dễ dàng quản lý hơn.

4. Dễ Dàng Sử Dụng Các Tính Năng React

  • Sử Dụng State và Effect Một Cách Dễ Dàng: useStateuseEffect là hai hooks cơ bản giúp bạn sử dụng state và side effects trong function components một cách dễ dàng.
  • Truy Cập Context Một Cách Dễ Dàng: useContext cho phép bạn truy cập dữ liệu từ React Context mà không cần phải sử dụng Consumer component.

5. Tối Ưu Hiệu Suất

  • Tránh Re-renders Không Cần Thiết: Sử dụng useMemouseCallback giúp tránh re-renders không cần thiết, tối ưu hiệu suất ứng dụng.

Tóm lại, React Hooks mang lại nhiều lợi ích như việc viết component dễ dàng và gọn gàng hơn, tái sử dụng logic một cách dễ dàng, code dễ hiểu và dễ bảo trì, dễ dàng sử dụng các tính năng React, và giúp tối ưu hiệu suất ứng dụng.

15

Sự khác biệt giữa smart componentdumb component là gì?

Trong phát triển ứng dụng React, thuật ngữ "smart" component (còn được gọi là container component) và "dumb" component (còn được gọi là presentational component) thường được sử dụng để mô tả hai loại component khác nhau dựa trên vai trò và chức năng của chúng trong ứng dụng.

Smart Components

  • Chức năng: Smart components thường chứa logic ứng dụng, quản lý trạng thái (state), xử lý dữ liệu và tương tác với các API hoặc services. Chúng thường làm việc với dữ liệu, quản lý các sự kiện và chịu trách nhiệm gửi dữ liệu đến các dumb components thông qua props.
  • Trách nhiệm: Chúng thường chịu trách nhiệm về cách ứng dụng hoạt động, bao gồm việc lấy dữ liệu, xử lý logic và quản lý trạng thái.
  • Ví dụ: Một smart component có thể là một container chứa form đăng nhập, nơi nó quản lý trạng thái của các input và xử lý việc gửi form.

Dumb Components

  • Chức năng: Dumb components thường chỉ tập trung vào việc hiển thị UI và không chứa logic ứng dụng hoặc trạng thái nội bộ. Chúng nhận dữ liệu dưới dạng props và hiển thị UI dựa trên dữ liệu đó.
  • Trách nhiệm: Chúng chịu trách nhiệm về cách ứng dụng trông như thế nào, bao gồm cấu trúc HTML, CSS và các yếu tố trực quan khác.
  • Ví dụ: Một dumb component có thể là một button, card hoặc một list item, nơi nó chỉ nhận props và hiển thị chúng mà không quản lý bất kỳ trạng thái nào.

Sự Khác Biệt Chính

  • Quản lý trạng thái: Smart components thường quản lý trạng thái ứng dụng và chứa logic, trong khi dumb components không quản lý trạng thái và chỉ tập trung vào việc hiển thị UI.
  • Tái sử dụng: Dumb components thường dễ tái sử dụng hơn vì chúng không phụ thuộc vào logic ứng dụng cụ thể, trong khi smart components có thể khó tái sử dụng hơn do chứa logic và trạng thái cụ thể.
  • Phụ thuộc: Smart components có thể phụ thuộc vào các services hoặc dữ liệu ứng dụng, trong khi dumb components chỉ phụ thuộc vào dữ liệu được truyền vào qua props.

Sự phân chia giữa smart và dumb components giúp tạo ra một cấu trúc ứng dụng rõ ràng và dễ quản lý, nơi logic ứng dụng được tách biệt khỏi UI, làm cho mã nguồn dễ đọc, dễ bảo trì và dễ tái sử dụng hơn.

16

Làm cách nào bạn ngăn một component hiển thị trong React?

Để ngăn một component hiển thị trong React, bạn có thể sử dụng một số cách sau:

1. Sử dụng Điều Kiện Trong JSX

Bạn có thể sử dụng một biểu thức điều kiện trong JSX để quyết định xem một component có được render hay không. Điều này thường được thực hiện bằng cách sử dụng toán tử ba ngôi hoặc các cấu trúc điều kiện khác như &&.

Ví dụ sử dụng toán tử ba ngôi:

jsx
function MyComponent({ shouldShow }) {
  return (
    <div>
      {shouldShow ? <ComponentToShow /> : null}
    </div>
  );
}

Ví dụ sử dụng &&:

jsx
function MyComponent({ shouldShow }) {
  return (
    <div>
      {shouldShow && <ComponentToShow />}
    </div>
  );
}

Trong cả hai ví dụ trên, ComponentToShow chỉ được render nếu shouldShowtrue.

2. Trả về null từ Component

Một component trong React có thể ngăn chính nó hiển thị bằng cách trả về null từ phương thức render (trong class component) hoặc từ chính bản thân nó (trong functional component).

Ví dụ với functional component:

jsx
function MyComponent({ shouldShow }) {
  if (!shouldShow) {
    return null;
  }

  return (
    <div>
      {/* Nội dung của component */}
    </div>
  );
}

Ví dụ với class component:

jsx
class MyComponent extends React.Component {
  render() {
    if (!this.props.shouldShow) {
      return null;
    }

    return (
      <div>
        {/* Nội dung của component */}
      </div>
    );
  }
}

Trong cả hai trường hợp, component sẽ không render gì cả nếu shouldShowfalse.

3. Sử dụng Higher-Order Components (HOC)

Bạn cũng có thể sử dụng một Higher-Order Component để kiểm soát việc hiển thị của một component. HOC là một hàm nhận vào một component và trả về một component mới với một số logic bổ sung - trong trường hợp này, logic để quyết định xem component gốc có được hiển thị hay không.

jsx
function withConditionalRendering(WrappedComponent) {
  return function({ shouldShow, ...props }) {
    if (!shouldShow) {
      return null;
    }

    return <WrappedComponent {...props} />;
  };
}

Sử dụng HOC:

jsx
const MyComponentWithConditionalRendering = withConditionalRendering(MyComponent);

// Trong JSX của bạn
<MyComponentWithConditionalRendering shouldShow={true} />

Sử dụng các phương pháp trên, bạn có thể dễ dàng kiểm soát việc hiển thị của các component trong ứng dụng React của mình.

17

Reselect là gì và nó hoạt động như thế nào?

Reselect là một thư viện selector cho Redux, giúp tạo ra các selector có thể được tái sử dụng và memoized. Selector là một hàm cho phép bạn trích xuất và chuyển đổi dữ liệu từ Redux store một cách hiệu quả. Reselect được sử dụng để tính toán dữ liệu phái sinh từ state của Redux store mà không cần phải viết lại logic tính toán mỗi khi state thay đổi.

Đặc điểm của Reselect

  • Memoization: Reselect sử dụng memoization để lưu trữ kết quả của selector. Khi một selector được gọi nhiều lần với cùng một state, nó sẽ trả về kết quả từ bộ nhớ cache thay vì tính toán lại, giúp tăng hiệu suất ứng dụng.
  • Composability: Selector trong Reselect có thể được kết hợp để tạo ra các selector phức tạp hơn. Bạn có thể tạo các selector "nhỏ" và kết hợp chúng để tạo ra các selector "lớn" mà không cần phải lo lắng về việc tính toán lại không cần thiết.
  • Tái sử dụng: Selector có thể được tái sử dụng trong nhiều component, giúp giảm bớt việc viết lại logic và tăng tính bảo trì của mã nguồn.

Cách hoạt động của Reselect

  1. Tạo Selector: Bạn tạo một selector bằng cách sử dụng hàm createSelector từ thư viện Reselect. Selector này sẽ nhận vào một hoặc nhiều "input selector" và một hàm "transform function" để tính toán và trả về dữ liệu mong muốn.

    javascript
    import { createSelector } from 'reselect';
    
    const getVisibilityFilter = state => state.visibilityFilter;
    const getTodos = state => state.todos;
    
    const getVisibleTodos = createSelector(
      [getVisibilityFilter, getTodos],
      (visibilityFilter, todos) => {
        switch (visibilityFilter) {
          case 'SHOW_COMPLETED':
            return todos.filter(t => t.completed);
          case 'SHOW_ACTIVE':
            return todos.filter(t => !t.completed);
          default:
            return todos;
        }
      }
    );
  2. Memoization: Khi selector được gọi, nó sẽ kiểm tra xem input đã thay đổi hay chưa. Nếu input không thay đổi, selector sẽ trả về kết quả từ bộ nhớ cache thay vì tính toán lại.

  3. Sử dụng trong Component: Bạn có thể sử dụng selector trong component của mình để trích xuất và chuyển đổi dữ liệu từ store một cách hiệu quả.

    javascript
    import { useSelector } from 'react-redux';
    
    const VisibleTodoList = () => {
      const visibleTodos = useSelector(getVisibleTodos);
      // Render UI dựa trên visibleTodos
    };

Kết luận

Reselect là một công cụ hữu ích trong việc quản lý và truy xuất state trong các ứng dụng Redux. Nó giúp tối ưu hóa hiệu suất bằng cách memoizing kết quả của các selector và cung cấp khả năng tái sử dụng và kết hợp các selector để xây dựng logic truy xuất dữ liệu phức tạp một cách dễ dàng và hiệu quả.

18

Làm thế nào để có thể tạo ref trong React?

Trong ReactJS, ref là một cách để truy cập trực tiếp một nút DOM hoặc một instance của một component trong React. Để tạo ref, bạn có thể sử dụng React.createRef() trong class components hoặc useRef() hook trong function components.

Class Components

Trong class components, bạn thường tạo ref bằng cách sử dụng React.createRef() trong constructor và sau đó gắn ref này vào một phần tử JSX bằng cách sử dụng thuộc tính ref.

javascript
import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  componentDidMount() {
    console.log(this.myRef.current); // Truy cập đến nút DOM hoặc component instance
  }

  render() {
    return <div ref={this.myRef}>Hello, World!</div>;
  }
}

Function Components

Trong function components, bạn có thể sử dụng useRef() hook để tạo ref. useRef trả về một đối tượng ref mà bạn có thể gắn vào phần tử JSX.

javascript
import React, { useRef, useEffect } from 'react';

function MyComponent() {
  const myRef = useRef(null);

  useEffect(() => {
    console.log(myRef.current); // Truy cập đến nút DOM
  }, []);

  return <div ref={myRef}>Hello, World!</div>;
}

Trong cả hai trường hợp, ref sẽ có một thuộc tính current mà thông qua đó bạn có thể truy cập đến nút DOM hoặc instance của component mà ref đã được gắn vào.

Lưu ý

  • Sử dụng ref chỉ khi thực sự cần thiết, ví dụ như để quản lý focus, chọn văn bản, hoặc thực hiện các thao tác truyền thống với DOM mà không thể thực hiện thông qua cơ chế state và props của React.
  • Tránh sử dụng ref để "hỏi" về trạng thái của component con, thay vào đó, nên sử dụng các cơ chế dữ liệu từ trên xuống như props hoặc context.

Tóm lại, ref trong ReactJS là một công cụ mạnh mẽ cho phép bạn truy cập trực tiếp vào nút DOM hoặc instance của component, nhưng nên được sử dụng một cách cẩn thận và hợp lý.

19

Làm sao để React build ở chế độ production và chúng có lợi ích như thế nào?

Trong React, việc build ứng dụng ở chế độ Production là một bước quan trọng để chuẩn bị triển khai ứng dụng của bạn lên môi trường sản xuất. Build ở chế độ Production giúp tối ưu hóa ứng dụng về mặt hiệu suất và bảo mật.

Cách Build React Ứng dụng ở Chế độ Production

Để build một ứng dụng React ở chế độ Production, bạn thường sử dụng các công cụ như Webpack hoặc các script được cung cấp bởi create-react-app (nếu bạn sử dụng boilerplate này để khởi tạo dự án). Dưới đây là các bước cơ bản:

  1. Sử dụng create-react-app:
    Nếu ứng dụng của bạn được khởi tạo bằng create-react-app, bạn có thể sử dụng script build đã được cấu hình sẵn:

    bash
    npm run build

    Hoặc nếu bạn sử dụng yarn:

    bash
    yarn build

    Lệnh này sẽ tạo ra một thư mục build chứa các tệp đã được tối ưu hóa cho môi trường sản xuất.

  2. Cấu hình Webpack:
    Nếu bạn tự cấu hình Webpack, bạn cần đảm bảo rằng bạn đã thiết lập đúng các plugin và loader để tối ưu hóa mã nguồn, như UglifyJsPlugin để minify mã JavaScript, MiniCssExtractPlugin để tối ưu hóa CSS, và các cấu hình khác để tối ưu hóa hình ảnh và tài nguyên.

  3. Thiết lập biến môi trường:
    Đảm bảo rằng bạn đã thiết lập biến môi trường NODE_ENV thành production. Điều này sẽ báo cho React biết rằng bạn đang build ứng dụng cho môi trường sản xuất, và React sẽ tối ưu hóa ứng dụng cho mục đích này.

    javascript
    process.env.NODE_ENV = 'production';

Lợi ích của việc Build ở Chế độ Production

  • Hiệu suất cao: Mã nguồn được minify và tối ưu hóa, giúp giảm kích thước tệp và thời gian tải trang.
  • Bảo mật: Việc loại bỏ mã nguồn dư thừa và thông báo lỗi chi tiết giúp tăng cường bảo mật cho ứng dụng.
  • Tối ưu hóa tài nguyên: Hình ảnh và các tài nguyên khác được tối ưu hóa để giảm băng thông và cải thiện thời gian tải.
  • Tương thích trình duyệt: Các tính năng mới của JavaScript được biên dịch xuống phiên bản tương thích với hầu hết các trình duyệt hiện đại.

Việc build ứng dụng React ở chế độ Production là một bước không thể thiếu trước khi triển khai ứng dụng, giúp đảm bảo rằng người dùng cuối có trải nghiệm tốt nhất khi sử dụng ứng dụng của bạn.

20

PureComponent trong React là gì?

PureComponent trong React là một lớp component mở rộng từ Component với một khác biệt chính: PureComponent tự động thực hiện một so sánh nông (shallow comparison) trên props và state của nó để quyết định xem component có cần được cập nhật hay không. Điều này giúp tối ưu hóa hiệu suất ứng dụng bằng cách tránh các lần re-render không cần thiết.

Đặc điểm của PureComponent:

  • So sánh nông (Shallow Comparison): PureComponent thực hiện một so sánh nông trên cả props và state. Nếu không có sự thay đổi nào được phát hiện, component sẽ không được cập nhật. So sánh nông có nghĩa là chỉ so sánh giá trị nguyên thủy và địa chỉ tham chiếu của đối tượng/ mảng, chứ không so sánh sâu các giá trị bên trong đối tượng hoặc mảng.
  • Tối ưu hóa hiệu suất: Bằng cách giảm số lượng lần re-render không cần thiết, PureComponent giúp tối ưu hóa hiệu suất, đặc biệt là trong các ứng dụng lớn và phức tạp.
  • Sử dụng cẩn thận: Khi sử dụng PureComponent, bạn cần đảm bảo rằng tất cả các props và state được sử dụng trong component đều là các giá trị nguyên thủy hoặc đối tượng/ mảng mà không thay đổi cấu trúc bên trong. Nếu không, PureComponent có thể không phát hiện được sự thay đổi và từ chối cập nhật component một cách không mong muốn.

Ví dụ về PureComponent:

javascript
import React, { PureComponent } from 'react';

class MyComponent extends PureComponent {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  incrementCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    console.log('Component re-rendered!');
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

Trong ví dụ trên, MyComponent sẽ chỉ được re-render khi state.count thực sự thay đổi. Nếu có bất kỳ hành động nào khác không thay đổi giá trị của state.count, PureComponent sẽ ngăn chặn việc re-render không cần thiết.

Tóm lại, PureComponent là một công cụ hữu ích trong React để tối ưu hóa hiệu suất ứng dụng bằng cách giảm số lượng lần re-render không cần thiết thông qua việc thực hiện so sánh nông trên props và state.

21

Refs được sử dụng như thế nào trong React?

Trong React, refs là một cách để truy cập trực tiếp một nút DOM hoặc một instance của một component từ bên trong component React. Refs thường được sử dụng khi bạn cần thực hiện các thao tác trực tiếp trên DOM hoặc khi cần truy cập trực tiếp đến một component con từ một component cha.

Cách tạo Refs

Trong React, bạn có thể tạo refs bằng cách sử dụng React.createRef() (trong React 16.3 trở lên) hoặc bằng cách sử dụng callback refs.

Sử dụng React.createRef()

javascript
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  render() {
    return <div ref={this.myRef} />;
  }
}

Sử dụng Callback Refs

javascript
class MyComponent extends React.Component {
  setMyRef = (element) => {
    this.myRef = element;
  }

  render() {
    return <div ref={this.setMyRef} />;
  }
}

Khi nào sử dụng Refs

  1. Quản lý focus, chọn văn bản, hoặc phát media: Khi bạn cần quản lý focus hoặc chọn văn bản trong một input, hoặc muốn phát hoặc dừng một video hoặc âm thanh.
  2. Kích hoạt các thao tác hoạt hình: Khi bạn cần thực hiện hoạt hình trực tiếp trên các phần tử DOM.
  3. Tích hợp với thư viện DOM bên ngoài: Khi bạn cần tích hợp React với thư viện bên ngoài mà cần truy cập trực tiếp đến DOM.

Lưu ý khi sử dụng Refs

  • Tránh sử dụng refs cho việc thực hiện logic xây dựng giao diện. Thay vào đó, hãy sử dụng state và props.
  • Sử dụng refs một cách cẩn thận vì việc truy cập trực tiếp và thay đổi DOM có thể làm giảm hiệu suất và khả năng dự đoán của ứng dụng.
  • Trong các component hàm, bạn có thể sử dụng Hook useRef để tạo refs.

Refs cung cấp một cách mạnh mẽ để tương tác với các phần tử DOM hoặc component con, nhưng cần được sử dụng một cách thông minh để không làm mất đi lợi ích của việc React quản lý DOM.

22

Ưu điểm của React là gì?

ReactJS, một thư viện JavaScript mạnh mẽ và linh hoạt cho việc xây dựng giao diện người dùng (UI), mang lại nhiều ưu điểm cho các nhà phát triển và doanh nghiệp. Dưới đây là một số ưu điểm chính của ReactJS:

1. Component-Based Architecture

ReactJS sử dụng kiến trúc dựa trên component, giúp phát triển các ứng dụng dễ dàng và hiệu quả. Mỗi component có thể quản lý trạng thái riêng của mình và được tái sử dụng ở nhiều nơi trong ứng dụng, giúp tăng cường tính bảo trì và tái sử dụng mã.

2. Virtual DOM

React sử dụng Virtual DOM để tối ưu hóa hiệu suất bằng cách giảm thiểu số lượng cập nhật DOM thực tế. Khi trạng thái của một component thay đổi, React sẽ cập nhật Virtual DOM trước, sau đó sử dụng thuật toán diffing để xác định những thay đổi cần thiết trên DOM thực tế, giúp tăng tốc độ và hiệu suất của ứng dụng.

3. One-Way Data Binding

ReactJS sử dụng mô hình dữ liệu một chiều (one-way data binding), giúp kiểm soát dòng dữ liệu trong ứng dụng và làm cho ứng dụng dễ debug hơn. Mô hình này cũng giúp các nhà phát triển dễ dàng theo dõi các thay đổi trong ứng dụng, từ đó tối ưu hóa và bảo trì dễ dàng hơn.

4. JSX

JSX là một cú pháp mở rộng cho JavaScript, cho phép viết cấu trúc UI trong mã JavaScript một cách dễ dàng và rõ ràng. JSX giúp mã nguồn dễ đọc và viết hơn, đồng thời cung cấp khả năng kiểm tra và tối ưu hóa mã nguồn tốt hơn.

5. Hỗ trợ mạnh mẽ từ cộng đồng

React được phát triển và bảo trì bởi Facebook cùng với sự đóng góp từ một cộng đồng lớn các nhà phát triển. Điều này đảm bảo rằng React luôn được cập nhật với các tính năng mới và hỗ trợ tốt cho các nhà phát triển.

6. Tính linh hoạt và tích hợp

React có thể được tích hợp với các thư viện và framework khác như Redux, React Router, hoặc thậm chí là Angular, giúp xây dựng các ứng dụng phức tạp và mạnh mẽ. Tính linh hoạt này cho phép các nhà phát triển chọn lựa công nghệ phù hợp nhất cho dự án của mình.

7. SEO Friendly

React có thể render trên server (sử dụng Node.js) giúp cải thiện khả năng tương thích với công cụ tìm kiếm (SEO) của ứng dụng web, một lợi thế lớn cho các dự án cần tối ưu hóa SEO.

Tóm lại, ReactJS mang lại nhiều lợi ích như kiến trúc dựa trên component, hiệu suất cao nhờ Virtual DOM, mô hình dữ liệu một chiều, cú pháp JSX dễ sử dụng, sự hỗ trợ mạnh mẽ từ cộng đồng, tính linh hoạt và khả năng tương thích tốt với SEO. Những ưu điểm này làm cho React trở thành một lựa chọn hàng đầu cho việc phát triển giao diện người dùng động và hiện đại.

23

Life Cycle trong React hoạt động như thế nào?

Life Cycle (Vòng đời) trong React mô tả quá trình mà một component trải qua từ khi được khởi tạo cho đến khi bị loại bỏ khỏi DOM. Vòng đời của một component trong React được chia thành ba giai đoạn chính: Mounting, Updating, và Unmounting.

Mounting

Mounting là giai đoạn mà component được tạo ra và chèn vào DOM. Các phương thức life cycle chính trong giai đoạn này bao gồm:

  • constructor(): Phương thức đầu tiên được gọi trong quá trình mounting. Thường được sử dụng để khởi tạo state và bind các phương thức event handler.
  • static getDerivedStateFromProps(): Được gọi ngay sau constructor và trước render(). Cho phép component cập nhật state dựa trên props ban đầu hoặc thay đổi props.
  • render(): Phương thức bắt buộc phải có. Trả về các element React mà bạn muốn hiển thị trên UI.
  • componentDidMount(): Được gọi sau khi component được chèn vào DOM. Thường được sử dụng để thực hiện các yêu cầu mạng, thiết lập các subscription, hoặc thao tác DOM.

Updating

Updating là giai đoạn mà component được cập nhật do thay đổi props hoặc state. Các phương thức life cycle trong giai đoạn này bao gồm:

  • static getDerivedStateFromProps(): Cũng được gọi trong giai đoạn này để cập nhật state dựa trên thay đổi props.
  • shouldComponentUpdate(): Cho phép bạn quyết định xem component có nên re-render hay không dựa trên thay đổi của props hoặc state.
  • render(): Được gọi lại để re-render UI với dữ liệu mới.
  • getSnapshotBeforeUpdate(): Được gọi trước khi thay đổi được áp dụng vào DOM. Dùng để thu thập thông tin từ DOM trước khi nó được thay đổi.
  • componentDidUpdate(): Được gọi sau khi component được cập nhật và re-render. Dùng để thực hiện các thao tác sau khi component được cập nhật.

Unmounting

Unmounting là giai đoạn cuối cùng của vòng đời component, khi component bị loại bỏ khỏi DOM. Có một phương thức life cycle trong giai đoạn này:

  • componentWillUnmount(): Được gọi trước khi component bị loại bỏ khỏi DOM. Thường được sử dụng để dọn dẹp các subscription, hủy bỏ các yêu cầu mạng, và thực hiện các tác vụ dọn dẹp.

Vòng đời của component trong React giúp bạn quản lý và kiểm soát quá trình render, cập nhật, và loại bỏ component một cách hiệu quả, đảm bảo rằng ứng dụng của bạn hoạt động mượt mà và hiệu quả.

24

Làm thế nào để bạn chặn callback của 1 event trong React?

Để chặn callback của một event trong React, bạn có thể sử dụng phương thức preventDefault() hoặc stopPropagation() trên đối tượng event được truyền vào hàm xử lý sự kiện (event handler).

Sử dụng preventDefault()

Phương thức preventDefault() được sử dụng để ngăn chặn hành vi mặc định của một sự kiện. Điều này hữu ích khi bạn muốn chặn các hành vi mặc định của trình duyệt, như việc gửi một form khi nhấn submit, hoặc chuyển trang khi nhấn vào một liên kết.

Ví dụ:

jsx
function handleSubmit(event) {
  event.preventDefault();
  // Logic xử lý khi form được submit
}

return (
  <form onSubmit={handleSubmit}>
    {/* Các thành phần của form */}
    <button type="submit">Submit</button>
  </form>
);

Trong ví dụ trên, preventDefault() được gọi trong hàm handleSubmit để ngăn chặn việc form được gửi đi một cách mặc định.

Sử dụng stopPropagation()

Phương thức stopPropagation() được sử dụng để ngăn chặn việc lan truyền của một sự kiện từ một phần tử con lên các phần tử cha của nó trong DOM. Điều này hữu ích khi bạn muốn chặn một sự kiện ở một phần tử con mà không muốn sự kiện đó ảnh hưởng đến các phần tử cha.

Ví dụ:

jsx
function handleClickChild(event) {
  event.stopPropagation();
  // Logic xử lý khi phần tử con được click
}

function handleClickParent() {
  // Logic này sẽ không được thực thi nếu phần tử con được click
}

return (
  <div onClick={handleClickParent}>
    <button onClick={handleClickChild}>Click Me</button>
  </div>
);

Trong ví dụ trên, stopPropagation() được gọi trong hàm handleClickChild để ngăn chặn việc sự kiện click trên nút bấm lan truyền lên phần tử cha, do đó hàm handleClickParent sẽ không được thực thi khi nút bấm được click.

Sử dụng preventDefault()stopPropagation() là hai cách phổ biến để chặn callback của một event trong React, tùy thuộc vào hành vi mà bạn muốn chặn.

25

SyntheticEvent trong React là gì?

SyntheticEvent trong ReactJS là một bao bọc cross-browser xung quanh native event của trình duyệt. Nó kết hợp hành vi của các sự kiện trình duyệt khác nhau thành một API chuẩn, đảm bảo rằng các sự kiện này hoạt động giống nhau trên tất cả các trình duyệt.

Đặc điểm của SyntheticEvent:

  • Tính nhất quán: SyntheticEvent cung cấp một API nhất quán cho các sự kiện, không phụ thuộc vào trình duyệt, giúp xử lý sự kiện dễ dàng và đáng tin cậy hơn.
  • Hiệu suất: React sử dụng một hệ thống tái sử dụng sự kiện để tăng hiệu suất. Khi sự kiện xử lý xong, tất cả các thuộc tính của sự kiện sẽ được nullify để đảm bảo không có rò rỉ bộ nhớ.
  • Hỗ trợ cho tất cả các sự kiện: SyntheticEvent hỗ trợ tất cả các sự kiện mà bạn có thể cần, từ cơ bản như click, input, và change, đến nâng cao hơn như drag and drop, touch, và các sự kiện khác.

Cách hoạt động của SyntheticEvent:

Khi bạn xử lý một sự kiện trong React, bạn không làm việc trực tiếp với native event. Thay vào đó, bạn làm việc với một instance của SyntheticEvent. React sẽ dịch native event thành SyntheticEvent và truyền nó vào hàm xử lý sự kiện của bạn.

Ví dụ về SyntheticEvent:

javascript
function handleClick(event) {
  console.log(event); // Đây là một SyntheticEvent
  console.log(event.type); // "click"
}

function MyComponent() {
  return <button onClick={handleClick}>Click me</button>;
}

Trong ví dụ trên, khi nút được click, hàm handleClick sẽ được gọi với một SyntheticEvent làm đối số. Bạn có thể truy cập các thuộc tính và phương thức của sự kiện giống như bạn làm với một native event, nhưng với sự đảm bảo rằng nó sẽ hoạt động giống nhau trên tất cả các trình duyệt.

Tóm lại, SyntheticEvent trong ReactJS giúp xử lý sự kiện trở nên nhất quán và dễ dàng hơn trên các trình duyệt khác nhau, đồng thời cung cấp hiệu suất tốt thông qua việc tái sử dụng sự kiện.

26

Element trong React là gì?

Element trong React là những khối xây dựng cơ bản nhất của ứng dụng React. Chúng mô tả những gì bạn muốn thấy trên màn hình. React elements là các đối tượng nhẹ và đơn giản mô tả một nút DOM, các thuộc tính của nó, và con của nó. Khác với trình duyệt DOM elements, React elements là các đối tượng thuần túy và dễ dàng tạo ra.

Đặc điểm của React Elements

  • Bất biến (Immutable): Một khi bạn tạo một element, bạn không thể thay đổi con của nó hoặc thuộc tính của nó. Một element giống như một bức ảnh chụp màn hình của một giao diện người dùng.
  • Hiệu quả: React DOM so sánh element và element con của nó với element trước đó để quyết định DOM cần cập nhật những gì để đạt được hiệu suất tối ưu.
  • Độc lập với platform: Có thể render elements vào nhiều loại môi trường khác nhau bằng cách sử dụng React DOM cho web, React Native cho mobile, và các renderer khác cho các platform khác.

Tạo và Render Elements

Để tạo một React element, bạn sử dụng React.createElement():

javascript
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

Để render một element vào DOM, bạn sử dụng ReactDOM.render():

javascript
ReactDOM.render(element, document.getElementById('root'));

Trong ví dụ trên, ReactDOM.render() sẽ thay đổi nội dung của nút DOM với id='root' để hiển thị "Hello, world!".

Lưu ý

  • Elements là những khối xây dựng cơ bản nhất của ứng dụng React và chúng tạo nên components.
  • Mặc dù elements là bất biến, ứng dụng React vẫn có thể thay đổi giao diện người dùng theo thời gian bằng cách render các elements mới phản ánh trạng thái mới.

Tóm lại, elements là cốt lõi của ứng dụng React, cho phép bạn mô tả giao diện người dùng của mình một cách đơn giản và hiệu quả.

27

Controlled component trong React là gì?

Trong React, một controlled component là một component mà giá trị của nó được quản lý bởi React state. Điều này có nghĩa là, thay vì để DOM quản lý trạng thái của dữ liệu nhập (như trong HTML truyền thống), trong React, component chứa form (ví dụ: <input>, <textarea>, và <select>) sẽ lưu trữ trạng thái trong state và cập nhật nó dựa trên mỗi thay đổi từ người dùng thông qua sự kiện.

Đặc điểm của Controlled Component

  • State Driven: Giá trị của form element (như input, select, textarea) được kiểm soát bởi state trong component React.
  • Sự kiện cập nhật: Mỗi khi có sự thay đổi trong form element, một sự kiện (thường là onChange) sẽ được kích hoạt, và state sẽ được cập nhật dựa trên giá trị mới.
  • Render dựa trên State: Component sẽ render lại mỗi khi state thay đổi, đảm bảo UI luôn đồng bộ với dữ liệu mới nhất.

Ví dụ

javascript
class ControlledComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Trong ví dụ trên, <input> là một controlled component vì giá trị của nó được kiểm soát bởi React state thông qua this.state.value và được cập nhật bằng this.handleChange.

Lợi ích

  • Tính nhất quán: Dữ liệu của form luôn đồng bộ với state, giúp dễ dàng kiểm soát và xử lý dữ liệu.
  • Validation: Dễ dàng thực hiện validation trên dữ liệu nhập vì mọi thay đổi đều được xử lý qua một hàm.
  • Tích hợp: Dễ dàng tích hợp với các tính năng khác của React như state management và lifecycle methods.

Controlled components cung cấp một cách mạnh mẽ và linh hoạt để xây dựng các form trong React, giúp quản lý dữ liệu nhập một cách hiệu quả và nhất quán.

28

Kể tên một số middleware của Redux mà bạn biết?

Trong Redux, middleware là một tầng trung gian cho phép bạn viết logic có thể tương tác với mỗi action được gửi đến store trước khi nó đạt đến reducer. Middleware có thể được sử dụng để xử lý logging, báo cáo về các lỗi, thực hiện các yêu cầu bất đồng bộ, và nhiều hơn nữa. Dưới đây là một số middleware phổ biến trong Redux:

1. Redux Thunk

  • Redux Thunk cho phép bạn viết action creators trả về một function thay vì một action. Điều này cho phép thực hiện các yêu cầu bất đồng bộ trong action creators của bạn.

2. Redux Saga

  • Redux Saga sử dụng các ES6 Generators để làm cho logic bất đồng bộ dễ quản lý và đọc hơn. Nó được sử dụng để xử lý các tác vụ phức tạp như truy cập dữ liệu bất đồng bộ, chạy nhiều tác vụ song song, và nhiều hơn nữa.

3. Redux Logger

  • Redux Logger cung cấp một cách dễ dàng để log mỗi action và trạng thái tiếp theo của store, giúp debug ứng dụng Redux dễ dàng hơn.

4. Redux Promise

  • Redux Promise cho phép bạn gửi promise như là payload trong action của bạn và dispatch một action mới khi promise được giải quyết hoặc bị từ chối.

5. Redux Observable

  • Redux Observable sử dụng RxJS để tạo ra và quản lý các side effect trong ứng dụng Redux của bạn. Nó cho phép bạn sử dụng các operators của RxJS để xử lý các tác vụ bất đồng bộ và logic phức tạp.

6. Redux Persist

  • Redux Persist cho phép bạn lưu trữ trạng thái của Redux store trong local storage của trình duyệt, giúp ứng dụng của bạn giữ trạng thái qua các phiên làm việc.

7. Redux DevTools Extension

  • Mặc dù không phải là middleware theo nghĩa truyền thống, Redux DevTools Extension cho phép bạn theo dõi mỗi thay đổi trạng thái trong store, thực hiện time travel debugging, và nhiều hơn nữa.

Các middleware này giúp mở rộng khả năng của Redux và cho phép xử lý các tác vụ phức tạp một cách dễ dàng hơn.

29

Sự khác nhau giữa class componentfunctional component trong Reactjs là gì?

Trong React, có hai loại chính để xây dựng components: class componentsfunctional components. Mỗi loại có đặc điểm và cách sử dụng riêng.

Class Components

  • Định nghĩa: Class components được định nghĩa bằng cách sử dụng ES6 classes. Chúng thường được sử dụng khi cần trạng thái (state) hoặc các phương thức lifecycle.
  • Trạng thái và Lifecycle: Class components cho phép bạn sử dụng các phương thức lifecycle như componentDidMount, componentDidUpdate, và componentWillUnmount. Chúng cũng cho phép sử dụng this.statethis.setState để quản lý trạng thái.
  • Cú pháp:
    jsx
    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { /* initial state */ };
      }
    
      componentDidMount() {
        // Lifecycle method
      }
    
      render() {
        return <div>{/* content */}</div>;
      }
    }
  • Binding this: Trong class components, bạn cần chú ý đến việc binding this khi truyền phương thức của component như một callback.

Functional Components

  • Định nghĩa: Functional components được định nghĩa bằng cách sử dụng các hàm JavaScript thông thường. Trước đây, chúng thường được sử dụng cho các components không có trạng thái (stateless) hoặc không cần sử dụng đến lifecycle methods.
  • Hooks: Với sự giới thiệu của Hooks trong React 16.8, functional components nay có thể sử dụng trạng thái và các tính năng khác của React thông qua useState, useEffect, và các hooks khác.
  • Cú pháp:
    jsx
    function MyComponent(props) {
      const [state, setState] = React.useState(initialState);
    
      React.useEffect(() => {
        // Side effects or lifecycle behavior
      });
    
      return <div>{/* content */}</div>;
    }
  • Simplicity và Performance: Functional components thường đơn giản hơn và có thể có hiệu suất tốt hơn do không có overhead của các phương thức lifecycle mà class components mang lại.

Sự Khác Biệt Chính

  • Cú pháp và Định nghĩa: Class components sử dụng cú pháp ES6 class và cần kế thừa từ React.Component, trong khi functional components là các hàm JavaScript đơn giản.
  • Trạng thái và Lifecycle: Trước khi có Hooks, chỉ class components mới có thể sử dụng trạng thái và lifecycle methods. Giờ đây, functional components cũng có thể sử dụng các tính năng này thông qua hooks.
  • this Binding: Chỉ class components mới cần quan tâm đến việc binding this, trong khi functional components không cần và thường dễ quản lý hơn.

Kết luận

Class componentsfunctional components đều có thể sử dụng để xây dựng UI trong React, nhưng với sự ra đời của Hooks, functional components trở nên mạnh mẽ hơn và được khuyến khích sử dụng do tính đơn giản và khả năng tái sử dụng mã cao. Class components vẫn còn hữu ích trong một số trường hợp, nhưng xu hướng hiện nay là chuyển dần sang sử dụng functional components.

30

Kể tên một số thư viện Flux phổ biến?

Flux là một kiến trúc ứng dụng được tạo ra bởi Facebook để sử dụng với thư viện React. Nó giúp tạo ra một luồng dữ liệu một chiều trong ứng dụng, giúp dễ dàng hơn trong việc theo dõi và quản lý trạng thái. Dưới đây là một số thư viện Flux phổ biến:

  1. Flux: Đây là thư viện Flux gốc được phát triển bởi Facebook. Nó cung cấp cấu trúc cơ bản của kiến trúc Flux, bao gồm Dispatcher, Stores và Actions.
  2. Redux: Mặc dù không phải là một thư viện Flux theo nghĩa truyền thống, Redux được lấy cảm hứng từ Flux và thường được sử dụng trong các ứng dụng React. Redux cung cấp một cách tiếp cận đơn giản hơn với một store duy nhất và các reducer để quản lý trạng thái.
  3. Alt: Alt là một thư viện Flux khác, cung cấp một cách tiếp cận đơn giản và linh hoạt hơn so với thư viện Flux gốc. Nó cung cấp các tính năng như tự động tạo actions và stores, và hỗ trợ các tính năng như async data fetching.
  4. Reflux: Reflux là một thư viện Flux đơn giản hóa mô hình bằng cách loại bỏ Dispatcher. Nó tập trung vào việc tạo ra một luồng dữ liệu một chiều và cho phép các stores lắng nghe các actions một cách trực tiếp.
  5. MobX: MobX không phải là một thư viện Flux, nhưng nó cung cấp một cách tiếp cận khác để quản lý trạng thái trong các ứng dụng JavaScript. MobX sử dụng các observable và actions để phản ứng với các thay đổi trạng thái và cập nhật UI một cách tự động.
  6. Fluxible: Đây là một thư viện Flux được xây dựng để hỗ trợ server-side rendering trong các ứng dụng React. Fluxible cung cấp một cấu trúc ứng dụng đầy đủ với các tính năng như điều hướng dựa trên context và plugin hệ thống.
  7. Flummox: Flummox là một thư viện Flux đã ngừng phát triển, nhưng nó đã cung cấp một cách tiếp cận không sử dụng singleton và không cần Dispatcher. Thay vào đó, nó sử dụng các class ES6 và promises để xử lý các actions và stores.

Các thư viện này cung cấp các cách tiếp cận khác nhau để triển khai kiến trúc Flux trong các ứng dụng React, giúp quản lý trạng thái và luồng dữ liệu một cách hiệu quả.

31

Cách để tránh phải liên kết với biến this trong các phương thức Event callback?

Để tránh phải liên kết với biến this trong các phương thức Event callback trong React, bạn có thể sử dụng một số cách sau:

1. Sử dụng Arrow Functions trong JSX

Arrow functions không có context this riêng, nên this trong arrow functions sẽ tham chiếu đến context this của phạm vi bên ngoài (thường là component).

Ví dụ:

jsx
class MyComponent extends React.Component {
  handleClick = () => {
    console.log(this); // 'this' tham chiếu đến instance của MyComponent
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}

2. Sử dụng Arrow Functions khi truyền Callback

Khi truyền callback, bạn có thể sử dụng arrow function ngay tại chỗ để đảm bảo this được liên kết đúng cách.

Ví dụ:

jsx
class MyComponent extends React.Component {
  handleClick() {
    console.log(this); // 'this' tham chiếu đến instance của MyComponent
  }

  render() {
    return <button onClick={() => this.handleClick()}>Click me</button>;
  }
}

3. Sử dụng Class Fields (Public Class Fields Syntax)

Đây là một tính năng của ES6+ cho phép bạn định nghĩa các phương thức của class dưới dạng arrow functions ngay trong phần khai báo của class.

Ví dụ:

jsx
class MyComponent extends React.Component {
  handleClick = () => {
    console.log(this); // 'this' tham chiếu đến instance của MyComponent
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}

4. Sử dụng React Hooks trong Functional Components

Nếu bạn sử dụng functional components, vấn đề liên kết this không còn tồn tại vì không có this trong functional components. Bạn có thể sử dụng hooks như useStateuseEffect để quản lý trạng thái và lifecycle.

Ví dụ:

jsx
function MyComponent() {
  const handleClick = () => {
    console.log('Clicked!'); // Không cần 'this' vì đây là functional component
  }

  return <button onClick={handleClick}>Click me</button>;
}

Sử dụng các cách trên giúp bạn tránh phải liên kết với this trong các phương thức event callback, giúp mã nguồn gọn gàng và dễ quản lý hơn.

32

Tại sao chúng ta nên sử dụng Redux?

Redux là một thư viện JavaScript phổ biến được sử dụng để quản lý trạng thái (state) ứng dụng. Nó hoạt động tốt với các thư viện như React và Angular để xây dựng các ứng dụng phức tạp. Dưới đây là một số lý do tại sao Redux được sử dụng rộng rãi:

1. Quản lý trạng thái dễ dàng

Redux cung cấp một cách tiếp cận dự đoán được và nhất quán để quản lý trạng thái ứng dụng. Trạng thái của toàn bộ ứng dụng được lưu trữ trong một cấu trúc dữ liệu duy nhất gọi là "store", giúp dễ dàng theo dõi các thay đổi trạng thái và quản lý trạng thái ứng dụng.

2. Dễ dàng debug và phát triển

Redux hỗ trợ các công cụ như Redux DevTools, cho phép các nhà phát triển theo dõi các hành động, thay đổi trạng thái, và điều hướng qua lại giữa các trạng thái trước đó của ứng dụng. Điều này làm cho việc debug trở nên dễ dàng hơn và giúp phát triển ứng dụng nhanh chóng.

3. Dễ dàng kiểm tra (testability)

Vì Redux sử dụng các hàm thuần túy (pure functions) cho reducers và hành động (actions), nó làm cho việc kiểm tra và viết unit tests trở nên dễ dàng hơn. Bạn có thể dễ dàng kiểm tra các reducers với các trạng thái và hành động khác nhau mà không cần phụ thuộc vào bất kỳ thư viện hoặc framework nào khác.

4. Tính nhất quán và dự đoán được

Redux giúp đảm bảo rằng trạng thái ứng dụng thay đổi một cách nhất quán và dự đoán được thông qua các hành động đã định nghĩa trước. Điều này giúp tránh các lỗi không mong muốn và làm cho ứng dụng của bạn dễ hiểu và dễ quản lý hơn.

5. Kiến trúc ứng dụng mạnh mẽ

Redux giúp xây dựng kiến trúc ứng dụng mạnh mẽ bằng cách khuyến khích việc phân tách logic ứng dụng thành các phần nhỏ, có thể tái sử dụng. Điều này không chỉ giúp quản lý mã nguồn dễ dàng hơn mà còn tạo điều kiện cho việc phát triển và bảo trì ứng dụng.

6. Cộng đồng và hỗ trợ mạnh mẽ

Redux có một cộng đồng lớn và nhiều tài nguyên học tập, bao gồm tài liệu, hướng dẫn, và các khóa học. Điều này giúp việc học và sử dụng Redux trở nên dễ dàng hơn cho các nhà phát triển mới.

Tóm lại, Redux là một công cụ mạnh mẽ cho việc quản lý trạng thái ứng dụng, đặc biệt là khi xây dựng các ứng dụng lớn và phức tạp. Nó cung cấp một cách tiếp cận nhất quán và dễ kiểm soát, giúp ứng dụng của bạn dễ phát triển và bảo trì.

33

Flow trong React là gì?

Flow là một trình kiểm tra kiểu tĩnh (static type checker) cho JavaScript, được phát triển bởi Facebook. Nó được thiết kế để tìm và báo cáo về các lỗi tiềm ẩn trong mã JavaScript thông qua việc phân tích kiểu dữ liệu của biến, hàm và các cấu trúc khác trong codebase của bạn.

Đặc điểm của Flow

  • Kiểm tra kiểu tĩnh: Flow giúp phát hiện lỗi liên quan đến kiểu dữ liệu trước khi chạy mã, giúp giảm thiểu lỗi runtime.
  • Tích hợp với IDE: Flow có thể tích hợp với các môi trường phát triển tích hợp (IDE) để cung cấp thông tin kiểu dữ liệu và gợi ý mã nguồn trong quá trình phát triển.
  • Tùy chọn kiểm tra kiểu: Flow cho phép bạn chọn lựa giữa việc kiểm tra kiểu một cách chặt chẽ hoặc linh hoạt, tùy thuộc vào cách bạn sử dụng comment kiểu dữ liệu trong mã nguồn.
  • Tương thích với ES6 và JSX: Flow hỗ trợ các tính năng mới nhất của JavaScript như ES6 và JSX, giúp nó trở thành công cụ kiểm tra kiểu mạnh mẽ cho các dự án hiện đại.

Cách hoạt động của Flow

Flow hoạt động bằng cách phân tích mã nguồn để xác định kiểu dữ liệu của biến và hàm. Bạn có thể khai báo kiểu dữ liệu một cách rõ ràng trong mã nguồn hoặc để Flow suy luận (infer) kiểu dữ liệu dựa trên cách sử dụng biến và hàm. Flow sau đó sẽ kiểm tra xem các kiểu dữ liệu có được sử dụng một cách nhất quán trong suốt ứng dụng hay không và báo cáo lỗi nếu có sự không khớp.

Ví dụ

javascript
// @flow
function square(n: number): number {
  return n * n;
}

square("2"); // Flow sẽ báo lỗi tại đây vì "2" không phải là kiểu number

Trong ví dụ trên, Flow sẽ báo lỗi khi bạn cố gắng gọi hàm square với một chuỗi thay vì một số, vì kiểu dữ liệu đã được khai báo rõ ràng là number.

Kết luận

Flow là một công cụ hữu ích cho các nhà phát triển JavaScript nhằm đảm bảo tính nhất quán và độ chính xác của kiểu dữ liệu trong ứng dụng, giúp phát hiện và sửa chữa lỗi sớm trong quá trình phát triển. Sử dụng Flow có thể giúp cải thiện chất lượng mã nguồn và giảm thiểu lỗi khi ứng dụng được triển khai.

34

Tại sao nên dùng fragment thay vì div trong React?

Trong React, việc sử dụng fragment thay vì div là một phương pháp tối ưu hóa hiệu suất và cải thiện cấu trúc của mã nguồn. Dưới đây là một số lý do chính giải thích tại sao nên sử dụng fragment thay vì div:

1. Tránh thêm các nút DOM không cần thiết

  • Fragment: Fragment cho phép bạn nhóm một danh sách các children mà không thêm các nút DOM extra vào cây DOM. Điều này giúp giảm bớt số lượng nút DOM không cần thiết, làm cho cây DOM gọn gàng hơn và cải thiện hiệu suất render.
  • Div: Sử dụng div để nhóm các children sẽ thêm một nút DOM mới vào cây DOM, có thể làm tăng kích thước của cây DOM và ảnh hưởng đến hiệu suất, đặc biệt trong các ứng dụng lớn.

2. Cải thiện cấu trúc mã nguồn

  • Fragment: Khi sử dụng fragment, bạn có thể giữ cho cấu trúc mã nguồn của mình sạch sẽ và rõ ràng hơn bằng cách tránh việc sử dụng các thẻ div không cần thiết chỉ để nhóm các phần tử.
  • Div: Việc sử dụng div không cần thiết có thể làm cho mã nguồn trở nên rối rắm và khó đọc, đặc biệt khi có nhiều lớp div lồng nhau.

3. CSS và Styling

  • Fragment: Fragment không tạo ra một nút DOM thực tế, do đó nó không ảnh hưởng đến CSS và styling của bạn. Điều này giúp tránh các vấn đề về styling không mong muốn do thêm các thẻ div không cần thiết.
  • Div: Sử dụng div có thể gây ra các vấn đề về styling, đặc biệt khi bạn không muốn thêm các thuộc tính CSS hoặc class không cần thiết vào các thẻ div chỉ để nhóm các phần tử.

4. Hỗ trợ Key trong danh sách

  • Fragment: Trong React 16.2 trở lên, bạn có thể sử dụng React.Fragment với prop key, điều này rất hữu ích khi bạn cần render một danh sách các fragment như một phần của một collection.
  • Div: Mặc dù div cũng có thể được sử dụng để render danh sách các phần tử, nhưng việc sử dụng div không cung cấp lợi ích về hiệu suất và cấu trúc mã nguồn như khi sử dụng fragment.

Kết luận

Việc sử dụng fragment thay vì div trong React giúp tối ưu hóa hiệu suất ứng dụng bằng cách giảm bớt số lượng nút DOM không cần thiết, cải thiện cấu trúc mã nguồn, và giảm thiểu các vấn đề về styling. Điều này làm cho ứng dụng của bạn trở nên hiệu quả và dễ bảo trì hơn.

35

So sánh điểm khác nhau của useRefcreateRef trong React gì?

useRefcreateRef trong React đều được sử dụng để tạo ra các refs, nhưng chúng có một số điểm khác biệt quan trọng:

useRef:

  • Hook useRef: useRef là một hook được giới thiệu trong React 16.8, cho phép bạn sử dụng refs trong function components.
  • Giữ giá trị qua re-renders: useRef trả về một đối tượng ref có thuộc tính current bền vững qua các lần re-render. Nghĩa là, nếu bạn gán một giá trị cho ref.current, giá trị đó sẽ giữ nguyên giữa các lần re-render, trừ khi bạn chủ động thay đổi nó.
  • Sử dụng trong Function Components: useRef thường được sử dụng trong function components vì class components không thể sử dụng hooks.
  • Có thể lưu trữ bất kỳ giá trị nào: Ngoài việc lưu trữ một nút DOM, useRef còn có thể lưu trữ bất kỳ giá trị nào bạn muốn giữ qua các lần re-render.

createRef:

  • Phương thức createRef: createRef là một phương thức của React dùng để tạo refs trong class components.
  • Tạo mới mỗi lần render: Mỗi lần component re-render, createRef sẽ tạo ra một đối tượng ref mới. Điều này có nghĩa là bạn không thể dựa vào createRef để giữ giá trị qua các lần re-render.
  • Sử dụng trong Class Components: createRef thường được sử dụng trong class components, nơi mà hooks không khả dụng.
  • Chủ yếu dùng để truy cập DOM: createRef thường được sử dụng để truy cập nút DOM hoặc component React sau khi component đã được mount.

So sánh:

  • Vòng đời: useRef giữ giá trị qua các lần re-render, trong khi createRef tạo ra một đối tượng ref mới mỗi lần component re-render.
  • Loại Component: useRef được sử dụng trong function components, createRef được sử dụng trong class components.
  • Cách sử dụng: useRef có thể lưu trữ bất kỳ giá trị nào và thường được sử dụng để giữ giá trị qua các lần re-render, trong khi createRef chủ yếu được sử dụng để truy cập nút DOM hoặc component React.

Tóm lại, useRefcreateRef đều tạo ra các refs nhưng được sử dụng trong các loại component khác nhau và có cách hoạt động khác nhau liên quan đến vòng đời của refs trong quá trình re-render của component.

36

Portal trong React là gì?

Portal trong ReactJS là một tính năng cho phép bạn render các component vào một phần tử DOM nào đó nằm ngoài phạm vi DOM của component cha. Điều này rất hữu ích khi bạn cần render một component mà không muốn bị giới hạn bởi CSS hoặc vị trí DOM của component cha, ví dụ như các hộp thoại (modals), tooltips hoặc các thông báo toàn cục.

Cách Sử Dụng Portal

Để sử dụng portal, bạn sẽ sử dụng hàm ReactDOM.createPortal() từ thư viện ReactDOM. Hàm này nhận vào hai đối số:

  1. React Element: Đây là component hoặc JSX mà bạn muốn render thông qua portal.
  2. Container DOM Node: Đây là phần tử DOM mà bạn muốn component được render vào.

Ví dụ:

jsx
import React from 'react';
import ReactDOM from 'react-dom';

class MyModal extends React.Component {
  render() {
    return ReactDOM.createPortal(
      // Bất kỳ JSX nào bạn muốn render
      <div className='modal'>
        {/* Nội dung của modal */}
      </div>,
      // Nơi bạn muốn modal được render trong DOM
      document.getElementById('modal-root')
    );
  }
}

Trong ví dụ trên, MyModal component sẽ được render vào phần tử có ID là modal-root trong DOM, bất kể vị trí của MyModal trong component tree của React.

Lợi Ích của Portal

  • Quản lý layout: Portal giúp bạn dễ dàng quản lý layout bằng cách cho phép render các component ra ngoài phạm vi của component cha, giúp tránh các vấn đề về CSS overflow hoặc z-index.
  • Tránh sự phức tạp: Khi sử dụng portal, bạn không cần phải quản lý trạng thái hoặc logic để hiển thị các component như modals hoặc tooltips ở nhiều nơi khác nhau trong ứng dụng của mình.
  • Tính linh hoạt: Portal cung cấp một cách linh hoạt để quản lý các phần của UI mà bạn muốn tách biệt với phần còn lại của ứng dụng, nhưng vẫn muốn giữ quản lý trạng thái hoặc dữ liệu thông qua React.

Portal mang lại một cách mạnh mẽ và linh hoạt để quản lý việc render các component trong React, giúp bạn dễ dàng tạo ra các trải nghiệm người dùng phức tạp và tùy chỉnh.

37

Sự khác nhau giữa createElementcloneElement trong React là gì?

Trong React, createElementcloneElement là hai phương thức có chức năng khác nhau:

createElement

  • Chức năng: createElement là một phương thức được sử dụng để tạo ra một React element mới từ một type (có thể là một tag HTML như 'div', 'span', hoặc một React component). Phương thức này thường được sử dụng khi bạn muốn tạo một element mà không cần viết JSX.
  • Cách sử dụng: createElement nhận vào ba tham số chính: type của element, một đối tượng chứa các props, và children của element đó.
  • Ví dụ:
    jsx
    React.createElement('div', { className: 'my-div' }, 'Hello World');
    Trong ví dụ trên, createElement tạo ra một element div với class 'my-div' và chứa nội dung là 'Hello World'.

cloneElement

  • Chức năng: cloneElement là một phương thức được sử dụng để sao chép và trả về một bản sao của React element với các props mới và/hoặc children mới. Phương thức này thường được sử dụng khi bạn muốn tạo một bản sao của một element với một số thay đổi nhỏ mà không cần tạo một element mới từ đầu.
  • Cách sử dụng: cloneElement nhận vào ba tham số: element cần được sao chép, một đối tượng chứa các props mới, và children mới cho element đó.
  • Ví dụ:
    jsx
    const element = <MyComponent foo="bar" />;
    const clonedElement = React.cloneElement(element, { foo: 'baz' }, 'New Children');
    Trong ví dụ trên, cloneElement tạo ra một bản sao của MyComponent, thay đổi prop foo thành 'baz' và thay thế children bằng 'New Children'.

Sự Khác Biệt Chính

  • Mục đích sử dụng: createElement được sử dụng để tạo một element mới, trong khi cloneElement được sử dụng để sao chép và chỉnh sửa một element đã tồn tại.
  • Thay đổi props và children: createElement tạo ra một element với props và children được xác định tại thời điểm tạo. cloneElement cho phép bạn thay đổi props và/hoặc children của một element đã có mà không ảnh hưởng đến element gốc.
  • Hiệu suất: cloneElement có thể hiệu quả hơn khi bạn chỉ cần thay đổi một số ít props hoặc children, vì nó không yêu cầu tạo một element mới từ đầu.

Cả createElementcloneElement đều là những công cụ quan trọng trong React, giúp bạn quản lý việc tạo và sao chép các React element một cách linh hoạt.

38

Higher-Order component trong React là gì?

Higher-Order Component (HOC) trong React là một kỹ thuật nâng cao trong React để tái sử dụng logic component. Một HOC không phải là một phần của API React chính thức, mà là một mô hình phát sinh từ thành phần hợp thành của React. Nói một cách đơn giản, một HOC là một hàm nhận vào một component và trả về một component mới.

Đặc điểm của Higher-Order Component:

  • Tái sử dụng code: HOC cho phép bạn tái sử dụng code, logic và bootstrap abstraction. HOC thường được sử dụng để chia sẻ logic giữa nhiều component, đặc biệt là khi logic đó không liên quan trực tiếp đến việc render UI.
  • Chuyển đổi props: HOC có thể sửa đổi props trước khi chúng được truyền đến component được bọc. Điều này có thể bao gồm việc thêm props mới, chỉnh sửa props hiện tại hoặc loại bỏ những props không cần thiết.
  • Abstract state: HOC có thể được sử dụng để quản lý state, và cung cấp các hành vi và thông tin liên quan đến state đó cho các component được bọc.

Cách hoạt động của Higher-Order Component:

Một HOC thường được định nghĩa như một hàm JavaScript thuần túy. Đây là một ví dụ về cách tạo một HOC:

javascript
function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ... thêm logic đăng ký...
    }

    componentWillUnmount() {
      // ... thêm logic hủy đăng ký...
    }

    render() {
      // ... và render WrappedComponent với dữ liệu mới...
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

Trong ví dụ trên, withSubscription là một HOC nhận vào một WrappedComponent và một hàm selectData. Hàm này tạo ra một class component mới, quản lý việc đăng ký và hủy đăng ký đến một nguồn dữ liệu, và truyền dữ liệu đó như một prop đến WrappedComponent.

Lưu ý khi sử dụng Higher-Order Component:

  • Không sử dụng HOC bên trong phương thức render: Điều này sẽ tạo ra một lượng lớn các component không cần thiết và có thể dẫn đến việc mất trạng thái và các vấn đề về hiệu suất.
  • Chuyển tiếp refs: Nếu bạn cần truy cập đến instance của component được bọc, bạn cần chuyển tiếp refs bằng cách sử dụng React.forwardRef.

Tóm lại, Higher-Order Component là một mô hình mạnh mẽ trong React giúp bạn tạo ra các component có thể tái sử dụng, tách biệt logic không liên quan đến UI và chia sẻ logic đó giữa các component khác nhau.

39

Bạn thích hooks nào trong React? Hãy mô tả cách tạo một hooks bất kỳ.

Trong React, Hooks là một tính năng được giới thiệu từ phiên bản 16.8, cho phép bạn sử dụng state và các tính năng React khác mà không cần phải viết một class. Hooks mang lại nhiều lợi ích như việc giúp code trở nên gọn gàng hơn, dễ đọc và dễ bảo trì hơn. Một trong những Hooks mà tôi thích nhất là useState vì nó cung cấp một cách đơn giản để thêm trạng thái local vào trong function components.

useState

useState là một Hook cơ bản cho phép bạn thêm trạng thái React vào trong function components. Khi bạn gọi useState trong một function component, React sẽ giữ giá trị này giữa các lần re-render của component.

Cách sử dụng

Để sử dụng useState, bạn chỉ cần nhập nó từ React và gọi nó trong function component của mình:

javascript
import React, { useState } from 'react';

function Counter() {
  // Khai báo một biến state mới, chúng ta gọi là "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Bạn đã click {count} lần</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Trong ví dụ trên, useState được gọi với giá trị khởi tạo là 0. Nó trả về một mảng với hai phần tử: giá trị hiện tại của trạng thái (count) và một hàm cho phép cập nhật giá trị đó (setCount). Khi bạn click vào nút, hàm setCount được gọi, dẫn đến việc component được re-render với giá trị mới của count.

Tạo Custom Hooks

Custom Hooks cho phép bạn tạo ra các Hooks riêng của mình, giúp tái sử dụng logic trạng thái giữa các components mà không cần phải dùng đến các pattern cao cấp như render props hay higher-order components.

Ví dụ về Custom Hook

Giả sử bạn muốn tạo một Hook để theo dõi vị trí chuột trong một component:

javascript
import { useState, useEffect } from 'react';

function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: null, y: null });

  useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({
        x: event.clientX,
        y: event.clientY
      });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return mousePosition;
}

Trong ví dụ trên, useMousePosition là một Custom Hook sử dụng useState để lưu trữ vị trí chuột và useEffect để thiết lập và dọn dẹp event listener. Bất kỳ component nào sử dụng useMousePosition sẽ có thể truy cập vào vị trí chuột hiện tại.

Tóm lại, Hooks trong React là một tính năng mạnh mẽ giúp bạn sử dụng state và các tính năng React khác trong function components. useState là một Hook cơ bản giúp quản lý trạng thái local, trong khi bạn cũng có thể tạo Custom Hooks để tái sử dụng logic trạng thái giữa các components.

40

Fragment trong React là gì?

Fragment trong React là một tính năng cho phép bạn nhóm nhiều phần tử con mà không cần thêm một nút DOM bổ sung vào cây DOM. Fragments giúp giữ cho DOM của bạn gọn gàng và tránh thêm các phần tử wrapper không cần thiết, giúp cải thiện hiệu suất và làm cho mã nguồn dễ quản lý hơn.

Cách Sử Dụng Fragments

Bạn có thể sử dụng Fragments bằng cách sử dụng thẻ <React.Fragment> hoặc sử dụng cú pháp ngắn gọn <> ... </>.

Ví dụ sử dụng <React.Fragment>:

jsx
import React from 'react';

function MyComponent() {
  return (
    <React.Fragment>
      <div>Child A</div>
      <div>Child B</div>
    </React.Fragment>
  );
}

Ví dụ sử dụng cú pháp ngắn gọn:

jsx
import React from 'react';

function MyComponent() {
  return (
    <>
      <div>Child A</div>
      <div>Child B</div>
    </>
  );
}

Trong cả hai ví dụ trên, MyComponent sẽ render hai div mà không cần thêm một phần tử wrapper nào khác như div hoặc span vào DOM.

Lợi Ích của Fragments

  • Tránh thêm phần tử wrapper không cần thiết: Fragments giúp bạn tránh việc phải thêm các phần tử DOM không cần thiết chỉ để nhóm các phần tử con lại với nhau.
  • Hiệu suất: Việc không thêm phần tử wrapper không cần thiết giúp giảm số lượng nút DOM, từ đó có thể cải thiện hiệu suất của ứng dụng.
  • Dễ dàng quản lý CSS và layout: Khi không cần thêm phần tử wrapper, bạn có thể dễ dàng quản lý CSS và layout mà không phải lo lắng về việc phần tử wrapper ảnh hưởng đến thiết kế của bạn.

Fragments là một công cụ hữu ích trong React, giúp bạn viết mã nguồn sạch sẽ và hiệu quả hơn khi làm việc với các nhóm phần tử con trong component của mình.

41

Props drilling là gì?

Props drilling là một thuật ngữ trong React để mô tả việc truyền dữ liệu từ một component cha xuống các component con thông qua props qua nhiều cấp độ của component tree. Khi một component cha có một mảng dữ liệu hoặc một callback function mà một component con sâu trong cây cần truy cập, bạn phải "khoan" (drill) props xuống qua mỗi cấp độ của cây cho đến khi nó đến được component cần thiết.

Ví dụ về Props Drilling

Giả sử bạn có một component App chứa một component Layout, và Layout này chứa một component Sidebar. Nếu App có một state mà Sidebar cần truy cập, bạn sẽ phải truyền state đó như một prop từ App đến Layout, rồi từ Layout truyền tiếp đến Sidebar.

jsx
// App component
function App() {
  const [user, setUser] = useState(null);

  return <Layout user={user} />;
}

// Layout component
function Layout({ user }) {
  return <Sidebar user={user} />;
}

// Sidebar component
function Sidebar({ user }) {
  return <div>{user ? user.name : 'Guest'}</div>;
}

Nhược điểm của Props Drilling

  • Khó quản lý: Khi ứng dụng phát triển và cây component trở nên phức tạp, việc truyền props qua nhiều cấp độ có thể trở nên khó quản lý và dễ gây lỗi.
  • Không linh hoạt: Mỗi khi cấu trúc của component tree thay đổi, bạn có thể phải sửa đổi nhiều component chỉ để truyền props đến nơi cần thiết.
  • Không hiệu quả: Props drilling có thể dẫn đến việc truyền dữ liệu không cần thiết qua các component không sử dụng dữ liệu đó, làm giảm hiệu suất của ứng dụng.

Cách giải quyết Props Drilling

Để giải quyết vấn đề props drilling, React cung cấp một số giải pháp như:

  • Context API: Cho phép bạn chia sẻ dữ liệu giữa các component mà không cần truyền props qua nhiều cấp độ.
  • Composition: Sử dụng kỹ thuật composition để xây dựng các component linh hoạt hơn, cho phép bạn tránh việc truyền props không cần thiết.
  • State Management Libraries: Sử dụng các thư viện quản lý trạng thái như Redux hoặc MobX để quản lý trạng thái ứng dụng một cách trung tâm.

Props drilling là một phần tự nhiên của việc phát triển ứng dụng React, nhưng việc hiểu rõ về nó và biết cách sử dụng các công cụ và kỹ thuật để giảm thiểu hoặc tránh nó có thể giúp bạn xây dựng các ứng dụng React hiệu quả và dễ bảo trì hơn.

42

Liệt kê một vài giới hạn của React?

React là một thư viện JavaScript mạnh mẽ và linh hoạt cho việc xây dựng giao diện người dùng, nhưng nó không phải là giải pháp hoàn hảo cho mọi vấn đề và có một số giới hạn:

1. Chỉ tập trung vào View Layer

  • React chỉ giải quyết phần "View" trong mô hình MVC (Model-View-Controller), nghĩa là bạn cần phải tích hợp với các thư viện khác để có một giải pháp toàn diện cho ứng dụng web. Điều này có thể làm tăng độ phức tạp và yêu cầu thêm công sức để chọn và học cách sử dụng các thư viện bổ sung như Redux hoặc MobX cho quản lý trạng thái, và React Router cho điều hướng.

2. Học Curve

  • Mặc dù React được khen ngợi vì sự đơn giản và hiệu quả, nhưng việc học cách sử dụng nó đúng cách, cũng như học các thư viện bổ sung cần thiết cho một ứng dụng toàn diện, có thể mất thời gian. Đặc biệt là với sự xuất hiện của Hooks, có một lớp học mới cho các nhà phát triển để hiểu và áp dụng chúng một cách hiệu quả.

3. Hiệu suất với Ứng dụng Lớn

  • Trong một số trường hợp, React có thể không đủ hiệu quả với các ứng dụng lớn và phức tạp do cách nó xử lý DOM ảo và cập nhật giao diện người dùng. Việc tối ưu hóa hiệu suất, như tránh re-renders không cần thiết, có thể trở nên khó khăn và yêu cầu sự hiểu biết sâu sắc về cách React hoạt động.

4. JSX như một rào cản

  • JSX, cú pháp mở rộng cho JavaScript được sử dụng trong React, có thể là một rào cản cho những người mới bắt đầu. Mặc dù nó cung cấp một cách mạnh mẽ để mô tả giao diện người dùng, nhưng cú pháp của nó có thể gây nhầm lẫn cho những người không quen với việc trộn HTML và JavaScript.

5. Cập nhật và Tính tương thích

  • React thường xuyên nhận được các cập nhật và cải tiến, điều này tốt cho sự phát triển của thư viện nhưng cũng có thể gây khó khăn cho các nhà phát triển trong việc theo kịp. Các dự án lớn có thể gặp khó khăn khi nâng cấp phiên bản React do sự thay đổi trong API hoặc các tính năng mới.

Tóm lại, mặc dù React mang lại nhiều lợi ích cho việc phát triển giao diện người dùng, nhưng cũng có những giới hạn và thách thức mà các nhà phát triển cần xem xét khi chọn nó cho dự án của mình.

43

Sự khác biệt giữa VirtualDOMShadowDOM là gì?

Trong phát triển web, Virtual DOM và Shadow DOM là hai khái niệm quan trọng nhưng hoàn toàn khác biệt. Dưới đây là sự khác biệt chính giữa chúng:

Virtual DOM

  • Khái niệm: Virtual DOM là một bản sao nhẹ của Real DOM. Nó là một cấu trúc dữ liệu JavaScript mà thư viện như React sử dụng để cải thiện hiệu suất bằng cách giảm thiểu số lượng cập nhật DOM thực tế.
  • Cách hoạt động: Khi trạng thái của ứng dụng thay đổi, React sẽ cập nhật Virtual DOM trước. Sau đó, nó so sánh Virtual DOM với bản sao trước đó để xác định những thay đổi cần thiết và chỉ áp dụng những thay đổi đó lên Real DOM.
  • Mục đích: Mục đích chính của Virtual DOM là tối ưu hóa hiệu suất ứng dụng bằng cách giảm thiểu số lượng và phạm vi của các thao tác DOM, vốn là tốn kém về mặt hiệu suất.

Shadow DOM

  • Khái niệm: Shadow DOM là một công nghệ web cho phép bạn tạo ra các DOM độc lập và ẩn cho các phần tử web, giúp đóng gói HTML, CSS, và JavaScript.
  • Cách hoạt động: Shadow DOM cho phép các nhà phát triển tạo ra "shadow trees" - các cây DOM riêng biệt được gắn với các phần tử nhưng hoạt động độc lập với main document DOM. Điều này giúp đóng gói mã và phong cách, ngăn chặn sự xung đột và tăng tính tái sử dụng của các thành phần.
  • Mục đích: Mục đích của Shadow DOM là cung cấp cách thức đóng gói và bảo vệ mã, giúp các web component có thể được sử dụng lại mà không lo lắng về sự xung đột với mã hoặc phong cách của phần còn lại của trang web.

Kết luận

  • Virtual DOM là một kỹ thuật tối ưu hóa hiệu suất được sử dụng bởi các thư viện như React để cải thiện tốc độ cập nhật UI.
  • Shadow DOM là một phần của Web Components, giúp đóng gói và bảo vệ mã, cho phép bạn tạo ra các thành phần web độc lập và tái sử dụng.

Cả hai đều giúp cải thiện quy trình phát triển web nhưng hoạt động theo những cách thức và mục đích khác nhau.

44

Trong React, có nên cập nhật state trực tiếp không, tại sao?

Trong React, bạn không nên cập nhật state trực tiếp vì những lý do sau:

1. Tính bất biến của State

State trong React được coi là bất biến, nghĩa là bạn không nên thay đổi (mutate) nó trực tiếp. Thay vào đó, bạn nên sử dụng phương thức setState() (trong class components) hoặc hook useState() (trong function components) để cập nhật state. Việc này giúp React theo dõi các thay đổi và quản lý việc cập nhật DOM một cách hiệu quả.

2. Cập nhật State Đồng Bộ

React có thể gom chung nhiều lần cập nhật state vào một lần để tối ưu hóa hiệu suất. Khi bạn cập nhật state trực tiếp, React không thể phát hiện được sự thay đổi này và không thể quản lý việc cập nhật DOM một cách chính xác.

3. Re-render Component

Khi sử dụng setState() hoặc useState(), React sẽ biết khi nào cần re-render component dựa trên sự thay đổi của state. Nếu bạn cập nhật state trực tiếp, component sẽ không re-render, và UI sẽ không phản ánh trạng thái mới của ứng dụng.

4. Tránh Lỗi Khó Phát Hiện

Cập nhật state trực tiếp có thể dẫn đến các lỗi khó phát hiện và khó debug vì nó vi phạm nguyên tắc dữ liệu bất biến mà React dựa trên. Điều này có thể gây ra hành vi không nhất quán trong ứng dụng của bạn.

5. Tính năng Của React

React cung cấp các phương thức và hooks để cập nhật state một cách chính xác và kiểm soát được. Việc sử dụng các công cụ này giúp đảm bảo rằng ứng dụng của bạn hoạt động như mong đợi và tận dụng được các tính năng tối ưu hóa của React.

Tóm lại, bạn không nên cập nhật state trực tiếp trong React vì nó vi phạm nguyên tắc bất biến của state, làm giảm khả năng React quản lý việc cập nhật UI, và có thể dẫn đến các lỗi không mong muốn trong ứng dụng của bạn.

45

Làm cách nào để liên kết các phương thức hoặc event handler trong lệnh callback JSX?

Trong React, việc liên kết các phương thức hoặc event handler trong lệnh callback JSX là quan trọng để đảm bảo rằng this trong phương thức đó tham chiếu đúng đến instance của component. Dưới đây là một số cách để liên kết các phương thức hoặc event handler:

1. Sử dụng Arrow Functions trong JSX

Arrow functions không có context this riêng, nên khi bạn sử dụng chúng trong JSX, this sẽ tham chiếu đến context bên ngoài - thường là instance của component. Điều này giúp tránh việc phải liên kết this một cách rõ ràng.

jsx
class MyComponent extends React.Component {
  myMethod() {
    console.log(this); // Tham chiếu đúng đến instance của MyComponent
  }

  render() {
    return <button onClick={() => this.myMethod()}>Click me</button>;
  }
}

2. Sử dụng .bind() trong JSX

Bạn có thể sử dụng phương thức .bind() để rõ ràng liên kết this với phương thức hoặc event handler khi truyền nó vào JSX. Tuy nhiên, cách này có thể gây ra việc tạo ra một hàm mới mỗi lần component render, ảnh hưởng đến hiệu suất.

jsx
class MyComponent extends React.Component {
  myMethod() {
    console.log(this); // Tham chiếu đúng đến instance của MyComponent
  }

  render() {
    return <button onClick={this.myMethod.bind(this)}>Click me</button>;
  }
}

3. Liên kết trong Constructor

Một cách hiệu quả hơn để liên kết this là sử dụng .bind() trong constructor của component. Cách này chỉ tạo ra một hàm liên kết duy nhất, không phụ thuộc vào số lần render.

jsx
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myMethod = this.myMethod.bind(this);
  }

  myMethod() {
    console.log(this); // Tham chiếu đúng đến instance của MyComponent
  }

  render() {
    return <button onClick={this.myMethod}>Click me</button>;
  }
}

4. Sử dụng Class Fields với Arrow Functions

Nếu bạn sử dụng Babel hoặc một trình biên dịch hỗ trợ class fields (đề xuất ECMAScript), bạn có thể định nghĩa phương thức hoặc event handler dưới dạng arrow function ngay trong class component. Cách này tự động liên kết this mà không cần phải sử dụng .bind().

jsx
class MyComponent extends React.Component {
  myMethod = () => {
    console.log(this); // Tham chiếu đúng đến instance của MyComponent
  }

  render() {
    return <button onClick={this.myMethod}>Click me</button>;
  }
}

Sử dụng một trong các cách trên giúp đảm bảo rằng this trong các phương thức hoặc event handler của bạn được liên kết đúng cách, cho phép bạn truy cập this.props, this.state, và các phương thức khác của component một cách an toàn.

46

StrictMode trong React là gì?

StrictMode trong React là một công cụ phát triển giúp phát hiện các vấn đề tiềm ẩn trong ứng dụng của bạn. Bằng cách bao bọc các component với StrictMode, React sẽ kích hoạt các kiểm tra và cảnh báo bổ sung cho các component con của nó. StrictMode không ảnh hưởng đến việc render của ứng dụng nhưng sẽ giúp bạn nhận biết về các sử dụng không an toàn của API, các vấn đề về side effects, lỗi sử dụng lỗi thời và các vấn đề khác mà có thể làm cho ứng dụng của bạn trở nên khó bảo trì hơn trong tương lai.

Các Tính Năng của StrictMode:

  • Phát hiện Component Không An Toàn: Cảnh báo về việc sử dụng các phương thức vòng đời không an toàn trong các component class.
  • Cảnh báo về Side Effects: Giúp phát hiện các vấn đề về side effects trong phương thức render bằng cách gọi hai lần các phương thức vòng đời và hàm tạo (constructor) trong giai đoạn phát triển.
  • Phát hiện Sử Dụng Lỗi Thời: Cảnh báo về việc sử dụng các API lỗi thời và không khuyến khích sử dụng.
  • Phát hiện Sử Dụng Không Mong Muốn: Cảnh báo về việc sử dụng một số tính năng như findDOMNode, mà có thể dẫn đến việc viết mã không tối ưu.
  • Phát hiện Vấn Đề về Context: Giúp phát hiện các vấn đề về sử dụng context không đúng cách.

Cách Sử Dụng StrictMode:

StrictMode được sử dụng bằng cách bao bọc các component với nó. Bạn có thể bao bọc toàn bộ ứng dụng của mình hoặc chỉ một phần của ứng dụng:

jsx
import React from 'react';

function App() {
  return (
    <React.StrictMode>
      <MyComponent />
    </React.StrictMode>
  );
}

Lưu ý rằng StrictMode chỉ kiểm tra các component con của nó, không kiểm tra chính nó. Nó cũng chỉ hoạt động trong môi trường phát triển; các kiểm tra và cảnh báo sẽ không xuất hiện trong sản phẩm cuối.

Tóm lại, StrictMode là một công cụ hữu ích trong React giúp bạn viết mã tốt hơn và phát hiện sớm các vấn đề tiềm ẩn, từ đó giúp ứng dụng của bạn trở nên bền vững và dễ bảo trì hơn.

47

Forwarding Refs trong React đển làm gì?

Forwarding Refs trong React là một kỹ thuật cho phép bạn chuyển một ref tự động qua một component để nó có thể truy cập đến một phần tử DOM con hoặc một instance của class component con. Điều này thường cần thiết khi bạn muốn một component cha có thể tương tác trực tiếp với một phần tử DOM hoặc component con mà không cần phải thêm các props trung gian hoặc logic bổ sung.

Cách Sử Dụng Forwarding Refs

Để sử dụng forwarding refs, bạn sẽ sử dụng hàm React.forwardRef để tạo một component. Hàm này nhận vào một hàm render và trả về một component React. Hàm render này nhận vào propsref như là tham số và trả về một React element.

Ví dụ:

jsx
const MyInput = React.forwardRef((props, ref) => (
  <input ref={ref} {...props} />
));

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  focusInput = () => {
    this.inputRef.current.focus();
  };

  render() {
    return (
      <>
        <MyInput ref={this.inputRef} />
        <button onClick={this.focusInput}>Focus the input</button>
      </>
    );
  }
}

Trong ví dụ trên, MyInput là một component được tạo ra bằng React.forwardRef. Khi ParentComponent render MyInput, nó chuyển ref mà nó tạo ra (this.inputRef) vào MyInput. MyInput sau đó chuyển ref này vào phần tử input DOM. Khi người dùng nhấn vào nút "Focus the input", phương thức focusInput của ParentComponent sẽ được gọi, và input sẽ được focus.

Lợi Ích của Forwarding Refs

  • Truy cập trực tiếp: Cho phép component cha truy cập trực tiếp đến một phần tử DOM hoặc instance của class component con.
  • Tái sử dụng: Giúp tái sử dụng các component con mà không cần thay đổi chúng để hỗ trợ refs.
  • Tính kết hợp: Cho phép kết hợp nhiều tính năng hoặc hành vi từ các component khác nhau mà không cần tạo ra một "prop drilling" phức tạp.

Forwarding refs là một công cụ hữu ích trong React, đặc biệt khi bạn cần tương tác với phần tử DOM hoặc quản lý focus, chọn văn bản, hoặc thực hiện các hoạt động tương tự mà không muốn vi phạm nguyên tắc của dữ liệu xuôi (data down, actions up).

48

Hàm setState trong React là đồng bộ hay bất đồng bộ? Tại sao?

Hàm setState trong Reactjs thường được coi là bất đồng bộ, vì React có thể gom chung nhiều lần gọi setState vào một lần cập nhật duy nhất để tối ưu hóa hiệu suất. Điều này có nghĩa là React có thể trì hoãn việc thực thi setState và sau đó cập nhật nhiều state cùng một lúc.

Tại sao setState là bất đồng bộ?

  1. Hiệu suất: Việc gom chung các lần cập nhật state giúp giảm số lượng re-renders không cần thiết, từ đó cải thiện hiệu suất của ứng dụng.
  2. Batching Updates: React sử dụng cơ chế "batching" để gom chung các lần cập nhật state. Khi một sự kiện được xử lý, như một click hoặc nhập liệu, React sẽ "batch" hoặc gom chung các lần gọi setState và áp dụng chúng cùng một lúc trong một chu trình cập nhật.
  3. Không đoán trước được: Do tính chất bất đồng bộ, bạn không thể chắc chắn về thời điểm chính xác mà state sẽ được cập nhật. Điều này có thể dẫn đến những vấn đề khi bạn cố gắng truy cập state ngay sau khi gọi setState.

Làm thế nào để xử lý tính bất đồng bộ của setState?

Callback Function: setState nhận một hàm callback làm tham số thứ hai, được gọi sau khi state đã được cập nhật và component đã re-render.

javascript
this.setState({ myState: newValue }, () => {
  console.log(this.state.myState); // Giá trị mới của state
});

Lifecycle Methods: Sử dụng các phương thức vòng đời của component như componentDidUpdate để làm việc với state sau khi nó đã được cập nhật.

Tóm lại, setState hoạt động một cách bất đồng bộ trong hầu hết các trường hợp để tối ưu hóa hiệu suất ứng dụng. Điều này đôi khi có thể gây ra nhầm lẫn, nhưng có thể được xử lý thông qua việc sử dụng hàm callback hoặc các phương thức vòng đời của component.

49

Làm thế nào để việc render của React hoạt động chính xác khi chúng ta gọi setState?

Trong React, việc render hoạt động chính xác khi gọi setState dựa trên một số nguyên tắc cơ bản của thư viện này:

1. Bất đồng bộ của setState

Khi bạn gọi setState, React sẽ lên lịch một cập nhật trạng thái cho component. Tuy nhiên, setState không cập nhật trạng thái ngay lập tức mà thay vào đó, nó khởi tạo một quá trình cập nhật bất đồng bộ. Điều này có nghĩa là React có thể gom chung nhiều lần gọi setState vào một lần cập nhật duy nhất để tối ưu hóa hiệu suất.

2. Quá trình cập nhật

Sau khi setState được gọi, React sẽ thực hiện các bước sau:

  • Lên lịch cập nhật: React sẽ lên lịch một cập nhật và đưa nó vào hàng đợi cập nhật.
  • Reconciliation: React sẽ so sánh phiên bản mới của component (với trạng thái đã được cập nhật) với phiên bản trước đó trong Virtual DOM. Quá trình này được gọi là reconciliation, nơi React xác định những phần nào của DOM cần được cập nhật.
  • Cập nhật DOM: Dựa trên kết quả của quá trình reconciliation, React sẽ cập nhật DOM thực tế để phản ánh trạng thái mới của component.

3. Vòng đời của Component

Trong class components, việc gọi setState sẽ kích hoạt một số phương thức vòng đời:

  • shouldComponentUpdate: Cho phép bạn quyết định xem component có nên cập nhật hay không dựa trên sự thay đổi của props hoặc state.
  • componentWillUpdate/UNSAFE_componentWillUpdate: Được gọi trước khi cập nhật xảy ra (được coi là lỗi thời và không khuyến khích sử dụng).
  • componentDidUpdate: Được gọi sau khi component đã được cập nhật trong DOM.

Trong function components, việc cập nhật trạng thái được quản lý thông qua hooks như useStateuseEffect.

4. Batch Updates

React thực hiện "batch updates" để tối ưu hóa quá trình cập nhật. Điều này có nghĩa là nhiều lần gọi setState có thể được gom chung và xử lý trong một lần cập nhật duy nhất, giúp giảm số lượng re-renders và tăng hiệu suất.

5. Không thay đổi trực tiếp state

Bạn không bao giờ nên thay đổi trạng thái trực tiếp bằng cách gán giá trị mới cho this.state vì React sẽ không biết được sự thay đổi này và không thể quản lý việc cập nhật DOM một cách chính xác.

Tóm lại, việc render trong React hoạt động chính xác khi gọi setState nhờ vào việc quản lý trạng thái một cách bất đồng bộ, quá trình reconciliation để xác định những thay đổi cần thiết trong DOM, và việc tối ưu hóa cập nhật thông qua batch updates.

50

Keys trong React được dùng để làm gì?

Trong React, key là một thuộc tính đặc biệt mà bạn nên bao gồm khi tạo danh sách các phần tử từ một mảng dữ liệu. Key giúp React xác định các phần tử nào đã thay đổi, được thêm vào, hoặc bị xóa, và nó là một phần quan trọng trong việc tối ưu hóa việc cập nhật và tái render của danh sách.

Mục đích của Key

  1. Hiệu Suất: Khi render một danh sách, React sử dụng các key để so sánh các phần tử giữa các lần render khác nhau. Nếu React phát hiện ra rằng một phần tử có key đã tồn tại trước đó, nó sẽ cập nhật phần tử đó thay vì tạo một phần tử mới, giúp cải thiện hiệu suất bằng cách tránh tái render không cần thiết.

  2. Tái Sử Dụng và Sắp Xếp: Khi danh sách thay đổi, React có thể tái sử dụng các phần tử có cùng key để cập nhật UI một cách nhanh chóng. Điều này đặc biệt hữu ích khi bạn cần sắp xếp hoặc lọc danh sách mà không muốn mất trạng thái bên trong các phần tử.

  3. Stability: Key giúp React duy trì sự ổn định của danh sách khi dữ liệu thay đổi, đảm bảo rằng mỗi phần tử được theo dõi một cách chính xác qua các lần cập nhật.

Cách Sử Dụng Key

Khi render một danh sách các phần tử, bạn nên cung cấp một key duy nhất cho mỗi phần tử trong danh sách. Key này thường là một ID duy nhất từ dữ liệu của bạn, nhưng có thể là bất kỳ giá trị nào duy nhất đối với mỗi phần tử.

jsx
const listItems = data.map((item) =>
  <li key={item.id}>
    {item.text}
  </li>
);

Trong ví dụ trên, item.id là một giá trị duy nhất được sử dụng làm key cho mỗi phần tử li.

Lưu Ý Khi Sử Dụng Key

  • Không sử dụng chỉ số mảng làm key nếu danh sách có thể thay đổi, vì điều này có thể gây ra các vấn đề về hiệu suất và hành vi không mong muốn.
  • Key phải là duy nhất trong phạm vi của danh sách, nhưng không cần phải là duy nhất toàn cục trong toàn bộ ứng dụng.

Key là một công cụ quan trọng giúp React quản lý danh sách một cách hiệu quả, đảm bảo rằng các cập nhật UI diễn ra nhanh chóng và chính xác.

51

Trong React uncontrolled component là gì?

Uncontrolled component trong React là một mẫu component mà trạng thái của nó không được quản lý bởi React. Trong uncontrolled components, dữ liệu form như giá trị của một input được xử lý bởi DOM thay vì bởi state trong component. Điều này có nghĩa là bạn sử dụng DOM như là "nguồn sự thật" để lấy giá trị hiện tại của input, thay vì lưu trữ giá trị đó trong state.

Cách Sử Dụng Uncontrolled Components

Để tạo một uncontrolled component, bạn thường sử dụng ref để truy cập trực tiếp đến phần tử DOM, thay vì sử dụng stateprops để kiểm soát các sự kiện như onChange. ref được sử dụng để lấy giá trị từ form khi cần thiết, chẳng hạn như khi form được gửi đi.

Ví dụ:

jsx
class MyForm extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  handleSubmit = (event) => {
    alert('A name was submitted: ' + this.inputRef.current.value);
    event.preventDefault();
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={this.inputRef} />
        </label>
        <button type="submit">Submit</button>
      </form>
    );
  }
}

Trong ví dụ trên, MyForm là một uncontrolled component vì nó sử dụng ref để lấy giá trị của input, thay vì quản lý giá trị đó thông qua state.

Lợi Ích và Nhược Điểm

Lợi Ích:

  • Đơn giản hóa component bằng cách giảm bớt số lượng state và logic cần quản lý.
  • Có thể dễ dàng tích hợp với các code DOM/thư viện bên ngoài không phải React.

Nhược Điểm:

  • Mất đi khả năng kiểm soát trạng thái của form từ React, điều này có thể làm giảm tính dự đoán và khả năng kiểm tra của ứng dụng.
  • Không thể sử dụng các tính năng của React như state và lifecycle methods để quản lý trạng thái của form.

Uncontrolled components thường được sử dụng khi bạn muốn tương tác trực tiếp với DOM hoặc khi bạn muốn giảm bớt số lượng logic trong component của mình. Tuy nhiên, trong hầu hết các trường hợp, controlled components (trạng thái được quản lý bởi React) được ưa chuộng hơn vì chúng cung cấp khả năng kiểm soát và linh hoạt cao hơn.

52

mapStateToPropsmapDispatchToProps trong redux là gì?

Trong Redux, mapStateToPropsmapDispatchToProps là hai hàm helper được sử dụng để kết nối một component React với Redux store. Chúng cho phép bạn lấy trạng thái và hành động từ store và chuyển chúng dưới dạng props đến component của bạn.

mapStateToProps

mapStateToProps là một hàm cho phép bạn trích xuất dữ liệu từ Redux store và chuyển chúng dưới dạng props đến component React của bạn. Hàm này nhận vào state của Redux store như là tham số đầu tiên và trả về một đối tượng chứa các props mà bạn muốn truyền vào component. Khi store thay đổi, mapStateToProps sẽ được gọi và component sẽ được render lại với các props mới.

javascript
function mapStateToProps(state) {
  return {
    todos: state.todos
  };
}

Trong ví dụ trên, mapStateToProps trích xuất todos từ state của Redux store và chuyển nó như một prop đến component.

mapDispatchToProps

mapDispatchToProps là một hàm cho phép bạn tạo ra các props callback mà khi được gọi sẽ dispatch một action đến Redux store. Hàm này nhận vào dispatch của Redux store như là tham số đầu tiên và trả về một đối tượng chứa các props mà bạn muốn truyền vào component. Các props này thường là các hàm mà khi được gọi sẽ dispatch một action để cập nhật trạng thái của store.

javascript
function mapDispatchToProps(dispatch) {
  return {
    addTodo: (text) => dispatch(addTodoAction(text))
  };
}

Trong ví dụ trên, mapDispatchToProps tạo ra một prop addTodo mà khi được gọi sẽ dispatch một action addTodoAction đến store.

Kết hợp với connect

mapStateToPropsmapDispatchToProps thường được sử dụng cùng với hàm connect từ thư viện react-redux để kết nối component với Redux store.

javascript
import { connect } from 'react-redux';

// Component của bạn
function TodoList(props) {
  // Sử dụng props.todos và props.addTodo trong component
}

// Kết nối Redux store với TodoList component
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

Khi sử dụng connect, mapStateToPropsmapDispatchToProps giúp định nghĩa cách mà dữ liệu và hành động từ store được chuyển đến component dưới dạng props, giúp component có thể tương tác với Redux store một cách dễ dàng và linh hoạt.

53

Hãy phân biệt Dom thật (real dom) và Dom ảo (virtual dom)?

Real DOM và Virtual DOM là hai khái niệm quan trọng trong phát triển web, đặc biệt là khi làm việc với các thư viện như React. Dưới đây là sự phân biệt chính giữa chúng:

Real DOM

  • Cập nhật chậm: Mỗi khi trạng thái của ứng dụng thay đổi, Real DOM cập nhật lại toàn bộ cây DOM, điều này có thể làm chậm hiệu suất ứng dụng.
  • Thao tác trực tiếp: Các thao tác trên Real DOM được thực hiện trực tiếp và có thể ảnh hưởng đến các nút DOM khác.
  • Tạo mới toàn bộ cây DOM: Khi cần cập nhật, toàn bộ cây DOM có thể được tạo mới, ngay cả khi chỉ có một phần nhỏ của UI thay đổi.
  • Tốn kém về hiệu suất: Thao tác trên Real DOM thường tốn kém về hiệu suất, đặc biệt là khi xử lý các ứng dụng lớn và phức tạp.

Virtual DOM

  • Cập nhật nhanh: Virtual DOM cho phép cập nhật hiệu quả bằng cách chỉ áp dụng những thay đổi thực sự cần thiết lên Real DOM.
  • Thao tác gián tiếp: Thay vì thao tác trực tiếp trên Real DOM, các thao tác được thực hiện trên bản sao của DOM (Virtual DOM), giúp giảm thiểu số lượng cập nhật trên Real DOM.
  • So sánh và cập nhật thông minh: Virtual DOM sử dụng thuật toán diffing để so sánh phiên bản hiện tại với phiên bản trước đó và chỉ cập nhật những phần thực sự thay đổi.
  • Hiệu suất cao: Việc sử dụng Virtual DOM giúp tăng hiệu suất ứng dụng, đặc biệt là trong việc xử lý các thay đổi dữ liệu thường xuyên và nhanh chóng.

Kết luận

Real DOM là cấu trúc dữ liệu mà trình duyệt sử dụng để render giao diện người dùng, trong khi Virtual DOM là một kỹ thuật được sử dụng trong các thư viện như React để tối ưu hóa việc cập nhật giao diện. Virtual DOM giúp cải thiện hiệu suất bằng cách giảm thiểu số lượng cập nhật trực tiếp trên Real DOM, từ đó mang lại trải nghiệm người dùng mượt mà và hiệu quả hơn.

54

Store trong redux là gì?

Store trong Redux là một đối tượng chứa trạng thái (state) của toàn bộ ứng dụng. Nó đóng vai trò là "single source of truth" (nguồn sự thật duy nhất) vì nó chứa tất cả dữ liệu cần thiết cho UI của ứng dụng. Store trong Redux có một số đặc điểm và chức năng chính sau:

Đặc Điểm của Store

  • Single Source of Truth: Store chứa trạng thái toàn bộ ứng dụng trong một đối tượng JavaScript duy nhất, giúp việc quản lý trạng thái trở nên dễ dàng và minh bạch.
  • Read-Only State: Trạng thái trong Store không thể được thay đổi trực tiếp. Thay vào đó, các thay đổi trạng thái được thực hiện thông qua việc gửi các hành động (actions) đến Store, mô tả "những gì đã xảy ra".
  • Changes with Pure Reducers: Để xác định cách trạng thái được cập nhật để phản hồi lại với các hành động, Redux sử dụng các reducers, là các hàm thuần không tạo ra các hiệu ứng phụ.

Chức Năng của Store

  • Lưu Trữ Trạng Thái: Store giữ trạng thái ứng dụng và là nơi duy nhất mà trạng thái có thể thay đổi.
  • Cho Phép Truy Cập Trạng Thái: Store cung cấp phương thức getState() để truy cập trạng thái hiện tại của ứng dụng.
  • Cập Nhật Trạng Thái: Store cho phép cập nhật trạng thái thông qua phương thức dispatch(action), nơi action là một đối tượng mô tả sự thay đổi muốn thực hiện.
  • Đăng Ký Lắng Nghe: Store cho phép các phần khác của ứng dụng đăng ký lắng nghe các thay đổi trạng thái thông qua phương thức subscribe(listener).
  • Xử Lý Thay Đổi: Khi một hành động được gửi đến Store, reducer sẽ xử lý hành động đó và trả về trạng thái mới, mà sau đó sẽ thay thế trạng thái hiện tại trong Store.

Store là một phần cốt lõi của kiến trúc Redux và là nền tảng cho việc quản lý trạng thái trong các ứng dụng JavaScript sử dụng Redux.

Store trong redux là gì
55

Bạn nên thực hiện request AJAX ở đâu trong một React component?

Trong một React component, yêu cầu AJAX nên được thực hiện trong phương thức vòng đời componentDidMount khi sử dụng class components, hoặc trong hook useEffect khi sử dụng function components. Điều này đảm bảo rằng yêu cầu AJAX chỉ được thực hiện sau khi component đã được gắn vào DOM, giúp tránh các vấn đề liên quan đến việc cập nhật trạng thái trên một component chưa sẵn sàng.

Class Components

javascript
class MyComponent extends React.Component {
  componentDidMount() {
    // Thực hiện yêu cầu AJAX ở đây
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  }

  // ...
}

Function Components

javascript
function MyComponent() {
  useEffect(() => {
    // Thực hiện yêu cầu AJAX ở đây
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => {
        // Cập nhật trạng thái hoặc thực hiện hành động khác với dữ liệu
      });
  }, []); // Mảng rỗng đảm bảo rằng effect chỉ chạy một lần sau khi component mount

  // ...
}

Sử dụng useEffect với mảng rỗng làm tham số thứ hai giúp đảm bảo rằng yêu cầu AJAX chỉ được thực hiện một lần sau khi component được mount, tương tự như componentDidMount trong class components.

56

Làm thế nào để tránh việc cần phải binding trong React?

Trong React, việc binding this trong các phương thức event handler là một bước cần thiết nếu bạn sử dụng ES6 class components và muốn truy cập this trong các phương thức đó. Tuy nhiên, việc này có thể trở nên lặp đi lặp lại và gây rối. Dưới đây là một số cách để tránh việc cần phải binding:

1. Sử dụng Public Class Fields Syntax

Bạn có thể sử dụng cú pháp class fields trong ES6+ để khai báo các phương thức như arrow functions, điều này tự động bind this cho bạn.

jsx
class MyComponent extends React.Component {
  handleClick = () => {
    console.log(this); // 'this' tự động được bind
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}

2. Sử dụng Arrow Functions trong JSX

Khi truyền event handlers vào JSX, bạn có thể sử dụng arrow functions để tự động bind this mà không cần phải làm điều đó trong constructor.

jsx
class MyComponent extends React.Component {
  handleClick() {
    console.log(this); // 'this' được bind đúng cách
  }

  render() {
    return <button onClick={() => this.handleClick()}>Click me</button>;
  }
}

Tuy nhiên, cách này có thể gây ra vấn đề về hiệu suất vì mỗi lần component render, một arrow function mới sẽ được tạo ra.

3. Sử dụng Hooks trong Functional Components

Nếu bạn sử dụng React 16.8 trở lên, bạn có thể sử dụng functional components với hooks thay vì class components. Trong functional components, không cần phải lo lắng về việc binding this vì không có this trong functional components.

jsx
function MyComponent() {
  const handleClick = () => {
    console.log('Clicked!');
  }

  return <button onClick={handleClick}>Click me</button>;
}

4. Binding trong Constructor (Khi cần)

Nếu bạn vẫn muốn sử dụng class components và không muốn sử dụng arrow functions trong JSX vì lý do hiệu suất, bạn có thể bind this trong constructor của class component.

jsx
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log(this); // 'this' được bind đúng cách
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>;
  }
}

Cách này đảm bảo rằng this được bind một lần duy nhất cho mỗi instance của component, giúp tránh việc tạo ra các hàm mới mỗi lần component render.

Sử dụng các cách trên giúp bạn tránh việc cần phải binding trong React, giúp mã nguồn gọn gàng và dễ quản lý hơn.

57

Children prop trong React là gì?

Trong React, children prop là một prop đặc biệt mà React cung cấp cho mỗi component. Nó chứa nội dung được truyền vào component từ bên ngoài, giúp bạn xây dựng các component có thể tái sử dụng và kết hợp với nhau một cách linh hoạt.

Đặc điểm của Children Prop

  • Nội dung động: children cho phép bạn truyền nội dung động vào trong component, bao gồm HTML, text, và thậm chí là các component khác.
  • Tái sử dụng: Sử dụng children giúp tạo ra các component có thể tái sử dụng với nội dung khác nhau mà không cần phải tạo ra nhiều component tương tự với những thay đổi nhỏ.
  • Composition: children là một phần quan trọng của cơ chế composition trong React, cho phép bạn xây dựng các cấu trúc UI phức tạp từ các component nhỏ và đơn giản.

Cách sử dụng Children Prop

Bạn có thể truyền children vào component như là nội dung giữa các thẻ mở và đóng của component đó trong JSX.

jsx
<MyComponent>
  <p>This is a child element</p>
</MyComponent>

Trong ví dụ trên, <p>This is a child element</p>children của MyComponent.

Trong component MyComponent, bạn có thể truy cập children thông qua props.children.

jsx
function MyComponent(props) {
  return <div>{props.children}</div>;
}

Sử dụng các API liên quan đến Children

React cung cấp một số API hữu ích trong React.Children để làm việc với children prop, bao gồm React.Children.map, React.Children.forEach, React.Children.count, React.Children.only, và React.Children.toArray. Những API này giúp bạn xử lý children một cách an toàn và hiệu quả khi children có thể là undefined, một object, hoặc một mảng các object.

jsx
React.Children.map(props.children, child => {
  // Làm gì đó với mỗi child
});

children prop là một công cụ mạnh mẽ trong React, giúp bạn xây dựng các component linh hoạt và tái sử dụng, từ đó tạo ra các ứng dụng có cấu trúc tốt và dễ bảo trì.

58

Redux là gì?

Redux là một thư viện JavaScript phổ biến dùng để quản lý trạng thái (state) cho các ứng dụng JavaScript. Nó thường được sử dụng với các thư viện giao diện người dùng như React, nhưng có thể được sử dụng với bất kỳ thư viện JavaScript nào khác. Redux cung cấp một cửa hàng trung tâm (central store) cho trạng thái của toàn bộ ứng dụng, giúp quản lý trạng thái trở nên dễ dàng và dự đoán được hơn.

image

Các Đặc Điểm Chính của Redux:

  • Single Source of Truth: Redux sử dụng một cửa hàng trung tâm để lưu trữ trạng thái toàn bộ ứng dụng, giúp việc quản lý trạng thái trở nên dễ dàng và minh bạch.
  • State is Read-Only: Trạng thái trong Redux không thể được thay đổi trực tiếp. Thay vào đó, các thay đổi trạng thái được thực hiện thông qua việc gửi các hành động (actions) đến cửa hàng, mô tả "những gì đã xảy ra".
  • Changes are Made with Pure Functions: Để xác định cách trạng thái được cập nhật để phản hồi lại với các hành động, Redux sử dụng các reducers, là các hàm thuần không tạo ra các hiệu ứng phụ.

Lợi Ích của Việc Sử Dụng Redux:

  • Dễ Dàng Quản Lý Trạng Thái: Quản lý trạng thái của ứng dụng trở nên dễ dàng hơn, đặc biệt là khi ứng dụng phát triển và trở nên phức tạp.
  • Dễ Dàng Debugging: Với một cửa hàng trung tâm, việc theo dõi, ghi nhật ký và debug trạng thái và hành động trở nên dễ dàng hơn.
  • Dễ Dàng Kiểm Soát Side Effects: Sử dụng middleware như Redux Saga hoặc Redux Thunk cho phép kiểm soát các hiệu ứng phụ một cách dễ dàng, giúp ứng dụng trở nên dễ dàng bảo trì và mở rộng.
  • Tính Dự Đoán Cao: Do trạng thái chỉ có thể thay đổi thông qua các hành động rõ ràng, ứng dụng trở nên dễ dàng dự đoán và kiểm soát hơn.

Khi Nào Nên Sử Dụng Redux:

  • Khi ứng dụng có trạng thái phức tạp cần được quản lý và chia sẻ giữa nhiều components.
  • Khi cần một giải pháp để quản lý trạng thái có khả năng mở rộng và dễ bảo trì.
  • Khi cần một cách thức minh bạch và dễ debug để quản lý trạng thái ứng dụng.

Tuy nhiên, Redux có thể không cần thiết cho các ứng dụng nhỏ hoặc các ứng dụng mà trạng thái có thể được quản lý một cách đơn giản thông qua các công cụ quản lý trạng thái cục bộ của React như Context API và Hooks.

59

PropTypes trong React để làm gì?

PropTypes trong React được sử dụng để kiểm tra kiểu dữ liệu của props mà một component nhận vào. Nó giúp đảm bảo rằng component đang nhận đúng loại props với đúng định dạng, giúp phát hiện lỗi và ngăn chặn lỗi tiềm ẩn khi phát triển ứng dụng.

Mục đích của PropTypes:

  • Kiểm tra kiểu dữ liệu: PropTypes cho phép bạn xác định kiểu dữ liệu cho mỗi prop mà component nhận vào, như string, number, array, object, bool, function, và nhiều kiểu khác.
  • Phát hiện lỗi: Khi một prop không phù hợp với kiểu dữ liệu đã định nghĩa, React sẽ hiển thị cảnh báo trong console, giúp phát hiện và sửa lỗi nhanh chóng trong quá trình phát triển.
  • Tài liệu mã nguồn: Sử dụng PropTypes cung cấp một dạng tài liệu mã nguồn, giúp các nhà phát triển khác hiểu được các props mà component cần và kiểu dữ liệu của chúng.

Cách sử dụng PropTypes:

Để sử dụng PropTypes, bạn cần cài đặt gói prop-types và sử dụng nó để xác định kiểu dữ liệu cho props:

javascript
import PropTypes from 'prop-types';

function MyComponent({ name, age, friends }) {
  // ...
}

MyComponent.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  friends: PropTypes.arrayOf(PropTypes.string)
};

Trong ví dụ trên, MyComponent có ba props: name là một chuỗi và bắt buộc phải có, age là một số, và friends là một mảng các chuỗi.

Lưu ý:

  • PropTypes chỉ hoạt động trong môi trường phát triển và sẽ bị loại bỏ trong sản phẩm cuối cùng để tối ưu hóa hiệu suất.
  • Trong các phiên bản mới của React, bạn cũng có thể sử dụng TypeScript hoặc Flow để kiểm tra kiểu dữ liệu một cách tĩnh, cung cấp khả năng kiểm tra kiểu dữ liệu mạnh mẽ hơn.

Tóm lại, PropTypes là một công cụ hữu ích trong React giúp kiểm tra kiểu dữ liệu của props, phát hiện lỗi, và cung cấp tài liệu mã nguồn, từ đó giúp tăng cường chất lượng và khả năng bảo trì của ứng dụng.

60

Mô tả cách hoạt động của kiến trúc Flux?

Flux là một mẫu kiến ​​trúc thực thi luồng dữ liệu một chiều - mục đích cốt lõi của nó là kiểm soát dữ liệu để nhiều component có thể tương tác với dữ liệu đó mà không có nguy cơ ô nhiễm (without risking pollution).

Mẫu Flux là khái niệm chung; nó không dành riêng cho các ứng dụng React, cũng như không bắt buộc phải xây dựng một ứng dụng React. Tuy nhiên, Flux thường được các nhà phát triển React sử dụng vì các React component có tính chất khai báo - UI được hiển thị (View) chỉ đơn giản là một function của state (Store data).

Mô tả các hoạt động của kiến trúc Flux

Trong mẫu Flux, Store là cơ quan trung tâm cho tất cả dữ liệu; bất kỳ thay đổi nào đối với dữ liệu phải xảy ra trong Store. Các thay đổi đối với Store data sẽ được truyền đến View qua các event. Sau đó, View sẽ tự cập nhật dựa trên state mới của dữ liệu đã nhận.

Để yêu cầu thay đổi bất kỳ Store data nào, Actions có thể được kích hoạt. Các Action này được kiểm soát bởi một Central Dispatcher;

Các Action sẽ không xảy ra đồng thời, đảm bảo rằng Store chỉ thay đổi dữ liệu một lần cho mỗi Action.

Luồng một chiều nghiêm ngặt của mẫu Flux này thực thi tính ổn định của dữ liệu, giảm các lỗi runtime liên quan đến dữ liệu trong một ứng dụng.

61

Mô tả cách xử lý các event trong React?

Trong React, việc xử lý các sự kiện (events) được thực hiện thông qua cơ chế tương tự như xử lý sự kiện trong HTML thuần túy, nhưng có một số khác biệt quan trọng và cải tiến nhất định. Dưới đây là cách xử lý các sự kiện trong React:

Đặt tên sự kiện

Trong React, tên của các sự kiện được viết theo cú pháp camelCase thay vì lowercase như trong HTML thuần túy. Ví dụ, thay vì sử dụng "onclick" trong HTML, bạn sẽ sử dụng "onClick" trong JSX của React.

Truyền hàm làm trình xử lý sự kiện

Trong React, bạn truyền một hàm vào thuộc tính của sự kiện để xử lý sự kiện đó. Hàm này có thể được định nghĩa trực tiếp trong JSX hoặc được tham chiếu từ một phương thức của class component.

Ví dụ với Function Component

javascript
function MyComponent() {
  function handleClick() {
    console.log('Button clicked');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

Ví dụ với Class Component

javascript
class MyComponent extends React.Component {
  handleClick() {
    console.log('Button clicked');
  }

  render() {
    return (
      <button onClick={this.handleClick.bind(this)}>
        Click me
      </button>
    );
  }
}

Truyền tham số cho trình xử lý sự kiện

Đôi khi bạn cần truyền tham số cho trình xử lý sự kiện. Trong React, bạn có thể làm điều này bằng cách sử dụng một arrow function hoặc hàm bind.

Sử dụng Arrow Function

javascript
<button onClick={(e) => this.handleClick(e, someData)}>
  Click me
</button>

Sử dụng .bind()

javascript
<button onClick={this.handleClick.bind(this, someData)}>
  Click me
</button>

Ngăn chặn hành vi mặc định

Để ngăn chặn hành vi mặc định của một sự kiện trong React, bạn có thể gọi preventDefault() trên đối tượng sự kiện được truyền vào hàm xử lý sự kiện.

javascript
function handleSubmit(e) {
  e.preventDefault();
  console.log('Form submitted');
}

// Trong JSX
<form onSubmit={handleSubmit}>
  <button type="submit">Submit</button>
</form>

Tổng kết

Xử lý sự kiện trong React tương tự như trong HTML thuần túy nhưng với một số cải tiến như cú pháp camelCase cho tên sự kiện, sử dụng hàm để xử lý sự kiện, và khả năng truyền tham số cho trình xử lý sự kiện. Việc sử dụng các hàm xử lý sự kiện giúp tạo ra các ứng dụng React linh hoạt và dễ bảo trì.

62

Tại sao React sử dụng className thay vì thuộc tính class?

Trong ReactJS, className được sử dụng thay vì thuộc tính class để xác định tên lớp CSS cho các phần tử DOM. Lý do chính cho việc này là class là một từ khóa dành riêng trong JavaScript, và JSX là một cú pháp mở rộng của JavaScript được sử dụng bởi React để mô tả UI.

Khi JSX được biên dịch thành JavaScript, nếu sử dụng từ khóa class, nó có thể gây ra xung đột với việc định nghĩa lớp trong JavaScript (ES6 classes). Để tránh vấn đề này và để JSX có thể hoạt động hài hòa với JavaScript, React sử dụng className để xác định tên lớp CSS.

Ngoài ra, việc sử dụng className giúp phân biệt rõ ràng giữa thuộc tính lớp CSS và khai báo lớp JavaScript, giúp mã nguồn dễ đọc và bảo trì hơn.

63

Tại sao phải gọi setState thay vì trực tiếp thay đổi state trong React?

Trong React, setState là phương thức được sử dụng để cập nhật state của một component. Việc gọi setState thay vì thay đổi state trực tiếp là quan trọng vì nhiều lý do:

Tính bất biến của State

  • State Immutability: Trong React, state được coi là bất biến (immutable). Điều này có nghĩa là bạn không nên thay đổi state trực tiếp bằng cách gán giá trị mới cho nó. Thay vào đó, bạn sử dụng setState để thông báo cho React về sự thay đổi và cho phép nó xử lý cập nhật state một cách an toàn.

Quy trình Cập nhật Component

  • Component Lifecycle: setState kích hoạt một quy trình cập nhật component, bao gồm việc gọi các phương thức lifecycle như shouldComponentUpdate, componentWillUpdate, render, và componentDidUpdate. Khi bạn thay đổi state trực tiếp, quy trình này không được kích hoạt, dẫn đến việc UI không được cập nhật để phản ánh sự thay đổi.

Hiệu suất

  • Performance Optimization: React sử dụng setState để tối ưu hóa hiệu suất bằng cách batch (nhóm) các cập nhật state và chỉ áp dụng những thay đổi cần thiết lên DOM. Khi bạn thay đổi state trực tiếp, bạn mất đi khả năng tối ưu hóa này.

Tính nhất quán

  • Consistency: Sử dụng setState đảm bảo rằng state và UI của component luôn đồng bộ. React sẽ quản lý state và đảm bảo rằng mọi thay đổi đều được phản ánh một cách nhất quán trên UI.

Kết luận

Gọi setState là cách chính xác để cập nhật state trong React vì nó đảm bảo rằng quy trình cập nhật component được thực hiện đúng cách, giữ cho state và UI đồng bộ, tối ưu hóa hiệu suất, và duy trì tính bất biến của state. Việc thay đổi state trực tiếp không chỉ là một thực hành không an toàn mà còn có thể dẫn đến các lỗi khó lường và khó debug trong ứng dụng của bạn.

64

Inline Conditional Expressions trong React là gì?

Inline Conditional Expressions trong React là một kỹ thuật sử dụng các biểu thức điều kiện JavaScript ngay trong JSX để điều khiển việc render của các thành phần. Điều này thường được thực hiện sử dụng toán tử ba ngôi (condition ? trueExpression : falseExpression) hoặc toán tử logic AND (condition && expression) để tạo điều kiện render một cách ngắn gọn và trực tiếp.

Toán tử ba ngôi

Toán tử ba ngôi cho phép bạn thực hiện một kiểm tra điều kiện và chọn một trong hai biểu thức để render dựa trên kết quả của điều kiện đó:

jsx
function Welcome(props) {
  return (
    <div>
      {props.isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign in.</h1>}
    </div>
  );
}

Trong ví dụ trên, nếu props.isLoggedIntrue, component sẽ render "Welcome back!", ngược lại sẽ render "Please sign in.".

Toán tử logic AND

Toán tử logic AND (&&) thường được sử dụng khi bạn chỉ muốn render một thành phần dựa trên một điều kiện mà không cần đến phần "else":

jsx
function Welcome(props) {
  return (
    <div>
      {props.isLoggedIn && <h1>Welcome back!</h1>}
    </div>
  );
}

Ở đây, "Welcome back!" chỉ được render nếu props.isLoggedIntrue. Nếu props.isLoggedInfalse, biểu thức sau toán tử && sẽ bị bỏ qua và không có gì được render.

Sử dụng Inline Conditional Expressions giúp mã JSX trở nên gọn gàng và dễ đọc hơn, đồng thời cho phép bạn tạo ra các logic render phức tạp mà không cần phải viết các câu lệnh điều kiện rời rạc hoặc sử dụng các phương thức render phụ trợ.

65

Chức năng của hàm render() trong React là gì?

Hàm render() trong React là một phương thức bắt buộc trong mỗi class component và có chức năng chính là trả về một phần tử React (React element) để mô tả những gì sẽ được hiển thị trên giao diện người dùng (UI). Nói cách khác, hàm render() xác định cấu trúc của giao diện người dùng bằng cách trả về các thành phần React, JSX, hoặc các loại nút DOM và component khác.

Đặc điểm của hàm render():

  • Được gọi tự động: React sẽ tự động gọi hàm render() mỗi khi trạng thái (state) hoặc props của component thay đổi, dẫn đến việc cập nhật giao diện người dùng.
  • Không thay đổi trạng thái: Hàm render() phải là một hàm "pure", nghĩa là nó không thay đổi trạng thái của component, không tương tác trực tiếp với trình duyệt, và trả về cùng một kết quả với cùng một tập hợp các đầu vào.
  • Trả về một phần tử: Hàm render() có thể trả về một phần tử React, một mảng các phần tử, chuỗi, số, hoặc null/false để không render gì cả.

Ví dụ về hàm render():

javascript
class MyComponent extends React.Component {
  render() {
    return (
      <div>
        Hello, {this.props.name}!
      </div>
    );
  }
}

Trong ví dụ trên, hàm render() trả về một phần tử div chứa một chuỗi chào mừng, sử dụng giá trị từ props của component.

Tóm lại, hàm render() là một phần không thể thiếu trong mỗi class component của React, đóng vai trò quan trọng trong việc xác định cách giao diện người dùng được cấu trúc và hiển thị.

66

Ba dấu chấm ... trong React để làm gì?

Trong React, ba dấu chấm (...), còn được gọi là spread operator, là một cú pháp ES6 được sử dụng để "trải" các phần tử của một mảng hoặc các thuộc tính của một đối tượng ra thành các phần tử hoặc thuộc tính riêng lẻ. Dưới đây là một số cách sử dụng spread operator trong React:

Truyền Props

Spread operator có thể được sử dụng để truyền toàn bộ props của một đối tượng đến một component một cách dễ dàng.

jsx
const myProps = { name: 'John', age: 30 };
<MyComponent {...myProps} />

Trong ví dụ trên, tất cả các thuộc tính trong myProps sẽ được truyền như là props đến MyComponent.

Kết hợp Đối tượng

Spread operator cũng có thể được sử dụng để kết hợp các đối tượng, tạo ra một đối tượng mới chứa tất cả các thuộc tính từ các đối tượng ban đầu.

javascript
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const combinedObj = { ...obj1, ...obj2 };

combinedObj sẽ là { a: 1, b: 2, c: 3, d: 4 }.

Sao chép Mảng

Spread operator cũng được sử dụng để tạo bản sao của mảng.

javascript
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];

copiedArray sẽ là một bản sao của originalArray.

Thêm Phần Tử vào Mảng

Spread operator cho phép bạn thêm phần tử vào mảng một cách dễ dàng.

javascript
const someArray = [1, 2, 3];
const extendedArray = [...someArray, 4, 5];

extendedArray sẽ là ``.

Truyền Arguments

Spread operator có thể được sử dụng để truyền một mảng các giá trị vào một hàm như là các đối số riêng lẻ.

javascript
function myFunction(x, y, z) { /* ... */ }
const args = [0, 1, 2];
myFunction(...args);

Trong ví dụ trên, myFunction được gọi với các đối số 0, 1, và 2.

Tóm lại, spread operator là một công cụ hữu ích trong React và JavaScript nói chung, giúp việc làm việc với mảng và đối tượng trở nên linh hoạt và dễ dàng hơn.

67

React có re-render tất cả các components và sub components mỗi khi gọi setState không?

Không, React không re-render tất cả các components và sub-components mỗi khi setState được gọi. React sử dụng một quá trình gọi là reconciliation để xác định những phần nào của component tree cần được cập nhật dựa trên sự thay đổi của state hoặc props.

Khi setState được gọi, React sẽ lên lịch một cập nhật và sau đó thực hiện các bước sau:

  1. Gọi phương thức render: React gọi phương thức render của component mà setState được gọi, cũng như của các sub-components của nó, để tạo ra một cây React elements mới.
  2. So sánh với Virtual DOM: React so sánh cây mới này với phiên bản trước đó của cây trong Virtual DOM để xác định những phần nào cần được cập nhật.
  3. Cập nhật DOM thực tế: React chỉ cập nhật những phần tử DOM thực tế cần thiết dựa trên sự khác biệt được xác định trong bước trước.
  4. Gọi lifecycle methods: Nếu có, React sẽ gọi các phương thức lifecycle như componentDidUpdate trên các component đã được cập nhật.

Do đó, không phải tất cả các components và sub-components đều được re-render. Chỉ những components có sự thay đổi trong output của phương thức render (do thay đổi state hoặc props) mới được React cập nhật. Điều này giúp tối ưu hóa hiệu suất và tránh việc re-render không cần thiết.

68

React hoạt động như thế nào?

React là một thư viện JavaScript được sử dụng để xây dựng giao diện người dùng (UI) đặc biệt là các ứng dụng một trang (SPA - Single Page Applications). React được phát triển bởi Facebook và hiện tại là một trong những thư viện front-end phổ biến nhất. Dưới đây là cách React hoạt động:

1. Component-Based Architecture

React sử dụng kiến trúc dựa trên component, nghĩa là UI được chia thành các phần nhỏ, độc lập gọi là components. Mỗi component có thể quản lý trạng thái (state) của nó và được tái sử dụng trong ứng dụng. Điều này giúp việc phát triển ứng dụng trở nên dễ dàng và hiệu quả hơn.

2. JSX

React sử dụng JSX, một cú pháp mở rộng cho JavaScript, cho phép viết cấu trúc UI giống như HTML trong mã JavaScript. JSX giúp mã nguồn dễ đọc và viết hơn, đồng thời cho phép React hiển thị thông tin từ mã JavaScript dễ dàng hơn thông qua cú pháp giống như template.

3. Virtual DOM

React sử dụng Virtual DOM để tối ưu hóa hiệu suất bằng cách giảm thiểu số lượng cập nhật DOM thực tế. Khi trạng thái của một component thay đổi, React sẽ tạo ra một Virtual DOM tree mới và so sánh nó với phiên bản trước đó để xác định những thay đổi cần được thực hiện trên DOM thực tế. Điều này giúp tăng tốc độ và hiệu suất của ứng dụng.

4. One-Way Data Binding

React thực hiện một chiều dữ liệu ràng buộc (one-way data binding), nghĩa là dữ liệu trong ứng dụng chỉ di chuyển theo một hướng từ parent components xuống child components thông qua props. Điều này giúp kiểm soát và theo dõi dòng dữ liệu trong ứng dụng dễ dàng hơn, giảm thiểu lỗi và tăng khả năng bảo trì.

5. React Hooks

React Hooks là một tính năng được giới thiệu trong React 16.8, cho phép sử dụng trạng thái và các tính năng khác của React mà không cần viết dưới dạng class. Hooks giúp viết các functional components mạnh mẽ hơn với ít code hơn và dễ dàng tái sử dụng logic giữa các components.

6. React Fiber

React Fiber là một cơ chế mới cho thuật toán reconciler của React, giúp cải thiện khả năng xử lý các tác vụ không đồng bộ, tối ưu hóa việc sử dụng tài nguyên và quản lý ưu tiên cập nhật UI. Fiber giúp React có thể thực hiện "time slicing" - chia nhỏ công việc và phân phối nó qua nhiều khung hình, giúp ứng dụng mượt mà hơn.

React hoạt động bằng cách kết hợp các tính năng này để tạo ra một thư viện mạnh mẽ, linh hoạt và hiệu quả cho việc phát triển giao diện người dùng.

69

Làm thế nào để truyền một parameter vào một event handler hoặc callback?

Để truyền một parameter vào một event handler hoặc callback trong React, bạn có thể sử dụng một arrow function hoặc function bên trong JSX. Điều này cho phép bạn gửi thêm dữ liệu vào hàm xử lý sự kiện khi nó được gọi.

Sử dụng Arrow Function

Bạn có thể truyền parameter trực tiếp vào một arrow function bên trong JSX:

jsx
<button onClick={(e) => this.handleClick(e, parameter)}>Click me</button>

Trong ví dụ trên, handleClick là hàm xử lý sự kiện, e là đối tượng sự kiện, và parameter là dữ liệu bạn muốn truyền vào hàm.

Sử dụng Function Binding

Nếu bạn đang sử dụng một class component, bạn có thể bind hàm xử lý sự kiện trong constructor và truyền parameter:

jsx
constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}

handleClick(parameter, e) {
  // Xử lý sự kiện ở đây
}

render() {
  return (
    <button onClick={(e) => this.handleClick(parameter, e)}>Click me</button>
  );
}

Trong ví dụ trên, handleClick được bind trong constructor để đảm bảo this được set đúng cách, và parameter được truyền vào khi gọi hàm.

Sử dụng Function Currying

Một cách khác là sử dụng function currying, nghĩa là tạo một hàm trả về một hàm khác:

jsx
handleClick = (parameter) => (e) => {
  // Xử lý sự kiện ở đây
}

render() {
  return (
    <button onClick={this.handleClick(parameter)}>Click me</button>
  );
}

Trong ví dụ trên, handleClick trả về một arrow function mới khi nó được gọi với parameter. Arrow function này sau đó sẽ được sử dụng như một event handler và có quyền truy cập vào parameter và đối tượng sự kiện e.

Sử dụng các phương pháp trên, bạn có thể dễ dàng truyền parameters vào event handlers hoặc callbacks trong React.

70

Single Page Applications là gì?

Single Page Applications (SPA) là các ứng dụng web mà khi sử dụng, trình duyệt chỉ cần tải một trang duy nhất từ máy chủ. Thay vì tải lại toàn bộ trang web khi người dùng tương tác với ứng dụng, SPA sử dụng JavaScript để tương tác với trang hiện tại và cập nhật nội dung mới.

Điều này có nghĩa là các tính năng và dữ liệu mới có thể được tải về và hiển thị trên cùng một trang mà không cần tải lại trang hoặc chuyển hướng sang trang khác. Điều này tạo ra trải nghiệm người dùng liền mạch và nhanh chóng hơn, vì người dùng không phải chờ đợi để tải lại toàn bộ trang web.

SPA thường sử dụng các framework JavaScript như React, Angular hoặc Vue.js để xây dựng các ứng dụng phức tạp. Các framework này cung cấp các công cụ và thư viện hỗ trợ cho việc quản lý trạng thái ứng dụng, định tuyến và tải dữ liệu từ máy chủ.

Một ưu điểm của SPA là khả năng tạo ra giao diện người dùng tương tác mượt mà và có trải nghiệm tương tự như ứng dụng máy tính. Tuy nhiên, việc tải toàn bộ mã và tài nguyên cần thiết cho ứng dụng ban đầu có thể làm cho thời gian tải ban đầu lâu hơn so với các ứng dụng truyền thống.

Với sự phát triển của công nghệ web, SPA đã trở thành một phong cách phát triển phổ biến và được sử dụng rộng rãi trong việc xây dựng các ứng dụng web hiện đại.

71

Làm thế nào để áp dụng validation trên Props trong React?

Trong ReactJS, việc áp dụng validation trên props giúp đảm bảo rằng các component nhận đúng loại dữ liệu và đúng định dạng dữ liệu từ props, từ đó giúp ứng dụng hoạt động chính xác và an toàn hơn. React cung cấp một cách để thực hiện điều này thông qua thư viện prop-types.

Sử dụng prop-types để Validate Props

  1. Cài đặt prop-types: Đầu tiên, bạn cần cài đặt thư viện prop-types nếu nó chưa được cài đặt trong dự án của bạn.
bash
npm install prop-types
  1. Áp dụng Validation: Sau khi đã cài đặt, bạn có thể sử dụng prop-types để xác định rõ ràng loại dữ liệu và các ràng buộc khác cho props của component.
jsx
import React from 'react';
import PropTypes from 'prop-types';

class MyComponent extends React.Component {
  render() {
    // Sử dụng props ở đây
  }
}

MyComponent.propTypes = {
  name: PropTypes.string.isRequired, // name phải là một string và là bắt buộc
  age: PropTypes.number, // age phải là một số
  onLogin: PropTypes.func, // onLogin phải là một hàm
  isStudent: PropTypes.bool, // isStudent phải là một giá trị boolean
  address: PropTypes.shape({ // address phải là một đối tượng với cấu trúc xác định
    street: PropTypes.string,
    city: PropTypes.string
  })
};

Trong ví dụ trên, MyComponent có một số props với các loại dữ liệu và ràng buộc cụ thể được xác định thông qua prop-types.

Lợi Ích của Việc Validate Props

  • Rõ Ràng và Dễ Hiểu: Việc xác định rõ ràng loại dữ liệu của props giúp code của bạn dễ đọc và dễ hiểu hơn.
  • Phát Hiện Lỗi Sớm: Validation giúp phát hiện lỗi liên quan đến dữ liệu không đúng định dạng ngay từ giai đoạn phát triển, giảm thiểu lỗi ở giai đoạn sản phẩm.
  • Tài Liệu Tự Động: Các định nghĩa prop-types cũng có thể coi như một hình thức tài liệu tự động cho các component của bạn, giúp các nhà phát triển khác trong dự án hiểu được cách sử dụng component.

Việc áp dụng validation trên props thông qua prop-types là một phương pháp hay được khuyến khích sử dụng trong ReactJS để tăng cường tính rõ ràng và độ tin cậy của ứng dụng.

72

Flux là gì?

Flux là một kiến trúc ứng dụng được phát triển bởi Facebook để xây dựng các ứng dụng giao diện người dùng (UI) phía client. Flux được thiết kế để giải quyết một số vấn đề với kiến trúc MVC (Model-View-Controller) truyền thống, đặc biệt là về việc quản lý dữ liệu và luồng dữ liệu trong các ứng dụng lớn và phức tạp.

Các Thành Phần Chính của Flux

Flux bao gồm bốn thành phần chính:

  1. Dispatcher: Là trung tâm điều khiển của kiến trúc Flux, nơi tất cả các hành động (actions) được gửi đến. Dispatcher quản lý tất cả các callbacks và đảm bảo rằng chúng được gọi theo đúng thứ tự.
  2. Stores: Lưu trữ và quản lý trạng thái ứng dụng. Trong Flux, mỗi store chứa một phần trạng thái ứng dụng và logic cụ thể liên quan đến phần trạng thái đó. Stores lắng nghe các hành động từ Dispatcher và cập nhật trạng thái ứng dụng tương ứng.
  3. Actions: Đại diện cho các sự kiện mà dữ liệu được gửi từ ứng dụng đến Dispatcher để được xử lý. Actions có thể được kích hoạt từ giao diện người dùng hoặc từ bất kỳ nơi nào trong ứng dụng.
  4. Views: Thành phần giao diện người dùng, thường được xây dựng bằng React trong các ứng dụng sử dụng Flux. Views lắng nghe sự thay đổi từ Stores và cập nhật giao diện người dùng tương ứng.

Luồng Dữ Liệu trong Flux

Flux áp dụng một mô hình luồng dữ liệu một chiều (unidirectional data flow), nghĩa là dữ liệu trong ứng dụng di chuyển theo một hướng rõ ràng từ Actions đến Dispatcher, sau đó đến Stores và cuối cùng đến Views. Mô hình này giúp quản lý trạng thái ứng dụng trở nên dễ dàng và dự đoán được hơn, đồng thời giảm thiểu sự phức tạp khi ứng dụng phát triển.

Lợi Ích của Flux

  • Dễ dàng quản lý trạng thái ứng dụng: Nhờ vào luồng dữ liệu một chiều và việc tách biệt rõ ràng giữa logic và trạng thái ứng dụng.
  • Tăng khả năng bảo trì và mở rộng: Các thành phần trong Flux được tách biệt rõ ràng, giúp dễ dàng thêm, sửa đổi hoặc loại bỏ chúng mà không ảnh hưởng đến phần còn lại của ứng dụng.
  • Tăng cường khả năng dự đoán và debug: Luồng dữ liệu một chiều giúp dễ dàng theo dõi và hiểu cách dữ liệu di chuyển trong ứng dụng.

Flux không phải là một thư viện hoặc framework cụ thể mà là một kiến trúc, và có thể được triển khai bằng nhiều cách khác nhau tùy thuộc vào yêu cầu cụ thể của ứng dụng.

73

Sự khác biệt giữa Presentational componentContainer component trong React là gì?

Trong React, sự phân biệt giữa Presentational component và Container component là một mô hình thiết kế giúp tách biệt trách nhiệm giữa việc quản lý dữ liệu và việc hiển thị giao diện người dùng. Mô hình này giúp tạo ra các ứng dụng dễ bảo trì, mở rộng và tái sử dụng.

Presentational Components

  • Chức năng: Chủ yếu quan tâm đến cách thức "trình bày" giao diện người dùng. Chúng mô tả cách giao diện trông như thế nào, không quan tâm đến logic ứng dụng hoặc cách dữ liệu được tải và thao tác.
  • Dữ liệu: Thường nhận dữ liệu và callbacks qua props. Không thường xuyên sử dụng hoặc thay đổi trạng thái (state) nội bộ, ngoại trừ trạng thái UI tương tác như mở/đóng một dropdown.
  • Đọc: Dễ đọc và tái sử dụng, vì chúng không phụ thuộc vào các phần khác của ứng dụng.
  • Ví dụ: Một button, một form, một layout chứa header và footer.

Container Components

  • Chức năng: Quan tâm đến cách thức "làm việc" của ứng dụng. Chúng cung cấp dữ liệu và hành vi (logic) cho các presentational hoặc các container component khác.
  • Dữ liệu: Thường giữ trạng thái (state) ứng dụng, gọi các API để tải dữ liệu, và xử lý các sự kiện.
  • Đọc: Có thể khó tái sử dụng và đọc hơn vì chúng thực hiện nhiều công việc và có nhiều phụ thuộc.
  • Ví dụ: Một component quản lý dữ liệu người dùng, xử lý việc tải dữ liệu từ server và truyền dữ liệu đó xuống các component con để hiển thị.

Lợi ích của việc phân biệt

  • Tái sử dụng: Presentational components có thể được tái sử dụng rộng rãi trong ứng dụng vì chúng không phụ thuộc vào logic ứng dụng cụ thể.
  • Phân tách trách nhiệm: Mô hình này giúp phân tách trách nhiệm giữa việc quản lý dữ liệu và việc hiển thị UI, làm cho ứng dụng dễ bảo trì và mở rộng hơn.
  • Dễ dàng quản lý: Việc tách biệt này giúp dễ dàng quản lý và debug ứng dụng khi ứng dụng phát triển và trở nên phức tạp hơn.

Tóm lại, việc phân biệt giữa Presentational và Container components trong React giúp tạo ra một cấu trúc ứng dụng rõ ràng, dễ quản lý và bảo trì, đồng thời tăng cường khả năng tái sử dụng của code.

74

Error Boundary được xử lý thế nào trong React?

Trong React, Error Boundary là một cơ chế cho phép bạn bắt và xử lý các lỗi JavaScript trong các phần của cây component, ngăn chặn lỗi từ việc "lan" ra toàn bộ ứng dụng. Error Boundary được xử lý bằng cách sử dụng các class component đặc biệt có thể bắt các lỗi xảy ra trong quá trình render, trong các phương thức lifecycle, và trong các constructor của toàn bộ cây component dưới chúng.

Cách sử dụng Error Boundary

Để tạo một Error Boundary, bạn cần định nghĩa một class component và sử dụng ít nhất một trong hai phương thức lifecycle sau:

  • static getDerivedStateFromError(error): Phương thức này được gọi khi một lỗi được ném ra từ một component con trong quá trình render. Nó trả về một đối tượng state mới dựa trên lỗi nhận được, cho phép bạn hiển thị một UI dự phòng.
  • componentDidCatch(error, info): Phương thức này được gọi sau khi lỗi xảy ra. Nó cho phép bạn ghi log lỗi và thu thập thông tin về lỗi, như stack trace.

Ví dụ về Error Boundary

javascript
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Cập nhật state để component tiếp theo có thể render UI dự phòng
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // Bạn cũng có thể log lỗi ra console hoặc gửi lỗi đến một dịch vụ báo cáo lỗi
    console.error("ErrorBoundary caught an error", error, info);
  }

  render() {
    if (this.state.hasError) {
      // Bạn có thể render bất kỳ UI dự phòng nào
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

Sử dụng Error Boundary trong Ứng dụng

Bạn có thể sử dụng Error Boundary bằng cách bọc nó quanh các component mà bạn muốn bảo vệ khỏi lỗi. Khi một lỗi xảy ra trong một component con của Error Boundary, UI dự phòng sẽ được render thay thế cho component gây ra lỗi.

javascript
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

Lưu ý

  • Error Boundary không bắt lỗi trong:
  • Event handlers (Bạn cần sử dụng try/catch trong event handlers)
  • Asynchronous code (ví dụ: setTimeout hoặc requestAnimationFrame callbacks)
  • Server-side rendering
  • Lỗi ném ra từ chính Error Boundary (thay vì các component con của nó)

Error Boundary là một tính năng quan trọng trong React giúp tăng cường độ tin cậy của ứng dụng bằng cách xử lý các lỗi không mong muốn một cách ân toàn và hiệu quả.

75

Context API trong ReactJS là gì?

Context API trong ReactJS là một cơ chế cho phép bạn truyền dữ liệu qua lại giữa các component mà không cần phải sử dụng props một cách thủ công từng cấp một. Nói cách khác, Context API cung cấp một cách để chia sẻ giá trị (như dữ liệu người dùng, theme, ngôn ngữ) giữa các component mà không cần phải truyền props ở mỗi cấp của cây component.

Context API được thiết kế để chia sẻ dữ liệu mà có thể được coi là "global" cho một cây của các component React, giúp giảm bớt sự phức tạp khi truyền dữ liệu giữa các component sâu trong cây component. Điều này đặc biệt hữu ích trong các ứng dụng lớn, nơi việc truyền props có thể trở nên cồng kềnh và khó quản lý.

Để sử dụng Context API, bạn sẽ tạo một Context bằng cách sử dụng React.createContext() và sau đó sử dụng Context.Provider để bao bọc cây component, cung cấp một giá trị cho Context đó. Các component con có thể truy cập giá trị Context này bằng cách sử dụng Context.Consumer hoặc Hook useContext().

Context API giúp quản lý trạng thái toàn cục của ứng dụng một cách dễ dàng hơn và là một phần của React từ phiên bản 16.3 trở đi.

76

Lifting State Up trong ReactJS là gì?

Lifting State Up trong ReactJS là một kỹ thuật được sử dụng để chia sẻ trạng thái giữa nhiều thành phần. Thay vì mỗi thành phần có trạng thái cục bộ riêng của mình, kỹ thuật này liên quan đến việc di chuyển quản lý trạng thái từ các thành phần con lên một tổ tiên chung (thành phần cha). Theo cách này, trạng thái trở thành "nguồn sự thật" cho các thành phần con, và chúng có thể truy cập và cập nhật nó thông qua props.

Ví dụ, xem xét một ứng dụng React với một thành phần gọi là máy tính có hai đầu vào. Mỗi đầu vào có trạng thái cục bộ của riêng mình, và chúng cần phản ánh cùng một dữ liệu thay đổi. Nếu một đầu vào thay đổi, đầu vào khác cũng nên phản ánh sự thay đổi này. Tuy nhiên, nếu mỗi đầu vào duy trì trạng thái cục bộ của mình, chúng không thể ảnh hưởng trực tiếp đến trạng thái của nhau. Đây là nơi "Lifting State Up" trở nên hữu ích. Bằng cách di chuyển trạng thái lên tổ tiên chung gần nhất (thành phần máy tính), chúng ta có thể đảm bảo rằng cả hai đầu vào đều đồng bộ.

"Lifting State Up" quan trọng vì nó giúp duy trì sự nhất quán trong dữ liệu hiển thị bởi các thành phần khác nhau. Nó đảm bảo rằng việc thay đổi dữ liệu trong một thành phần dẫn đến việc cập nhật cùng một dữ liệu trong tất cả các thành phần khác phụ thuộc vào nó. Điều này đặc biệt quan trọng trong các ứng dụng phức tạp, nơi nhiều thành phần có thể cần chia sẻ và hiển thị cùng một trạng thái.

Khi trạng thái được "nâng lên", nó trở thành "nguồn sự thật" cho các thành phần con. Các thành phần này nhận trạng thái dưới dạng props và chỉ có thể cập nhật nó bằng cách gọi một hàm được cung cấp bởi thành phần cha. Điều này đảm bảo rằng trạng thái luôn được giữ nhất quán và cập nhật.

77

Quá trình Reconciliation trong ReactJS là gì?

Quá trình Reconciliation trong ReactJS là một cơ chế mà React sử dụng để cập nhật hiệu quả DOM (Document Object Model) của trình duyệt và đảm bảo hiệu suất tối ưu. Khi các thành phần React được render, chúng tạo ra một cấu trúc giống như cây gọi là Virtual DOM (VDOM), là một biểu diễn nhẹ của DOM thực tế. Mỗi khi có sự thay đổi trong trạng thái (state) hoặc props của thành phần, React thực hiện quá trình Reconciliation để so sánh VDOM trước và sau khi thay đổi, và áp dụng chỉ những cập nhật cần thiết lên DOM thực tế.

Quá trình này bao gồm các bước chính sau:

  1. Tạo Element Mới: React tạo ra các element mới cho bất kỳ thành phần hoặc element mới nào xuất hiện trong quá trình render.
  2. Phương Pháp Diffing và Reconciliation: React thực hiện quá trình diffing bằng cách so sánh VDOM cũ và mới, tìm kiếm sự thay đổi, thêm mới hoặc loại bỏ. Trong quá trình Reconciliation, khi trạng thái của một thành phần thay đổi, React sẽ render lại thành phần đó và các thành phần con của nó.
  3. Cập Nhật DOM: React áp dụng các cập nhật cần thiết lên DOM thực tế, đảm bảo số lượng thay đổi tối thiểu để đạt được hiệu suất tối ưu.

Quá trình Reconciliation không chỉ giúp tối ưu hóa hiệu suất bằng cách giảm thiểu số lượng thao tác DOM cần thiết mà còn giúp cung cấp trải nghiệm người dùng mượt mà bằng cách đảm bảo rằng giao diện người dùng luôn phản ánh trạng thái mới nhất của ứng dụng. Để tăng cường hiệu quả của quá trình Reconciliation, React khuyến khích sử dụng thuộc tính key cho mỗi element trong một mảng được render bởi một thành phần, giúp React xác định chính xác các element nào đã được thêm, loại bỏ, hoặc di chuyển trong quá trình Reconciliation.

78

Components Composition trong React là gì?

Components Composition trong React là một kỹ thuật phát triển dựa trên mô hình thành phần gốc của React, nơi chúng ta xây dựng các thành phần từ các thành phần khác bằng cách sử dụng props children. Kỹ thuật này cho phép tạo ra các thành phần có thể tái sử dụng và mở rộng, giúp loại bỏ mã trùng lặp và làm cho ứng dụng dễ bảo trì hơn khi cần thêm tính năng mới mà không cần phải sửa đổi nhiều tệp.

Thành phần ghép là một khái niệm cốt lõi trong ReactJS, một thư viện JavaScript phổ biến để xây dựng giao diện người dùng. Trong ReactJS, các thành phần là các khối xây dựng của ứng dụng, và chúng có thể được kết hợp và tái sử dụng để tạo ra các thành phần phức tạp hơn. Thành phần ghép cho phép các nhà phát triển xây dựng các ứng dụng có cấu trúc mô-đun, có khả năng mở rộng và dễ bảo trì. Bằng cách chia ứng dụng thành các thành phần nhỏ hơn, các nhà phát triển có thể cô lập và gỡ lỗi vấn đề dễ dàng hơn, tái sử dụng mã ở các phần khác nhau của ứng dụng và thực hiện thay đổi nhanh chóng mà không ảnh hưởng đến các phần khác của ứng dụng.

Thành phần ghép trong ReactJS được thực hiện thông qua một số cơ chế khác nhau, chẳng hạn như sử dụng props để truyền dữ liệu giữa các thành phần và sử dụng các thành phần bậc cao (higher-order components) để bao bọc và nâng cao các thành phần hiện có. Ngoài ra, ReactJS cũng hỗ trợ một khái niệm được gọi là "render props", cho phép các thành phần nhận một hàm như một prop, mà sau đó chúng có thể sử dụng để render đầu ra của mình.

Có một số lợi ích khi sử dụng thành phần ghép trong ReactJS:

  • Tái sử dụng mã: Thành phần ghép cho phép tạo ra các thành phần nhỏ, tập trung và có thể tái sử dụng hoặc các mô-đun. Bằng cách tái sử dụng mã hiện có ở các phần khác nhau của ứng dụng, bạn giảm bớt sự trùng lặp và duy trì một cơ sở mã hiệu quả hơn.
  • Mô-đun: Việc ghép các ứng dụng từ các mô-đun nhỏ, độc lập giúp dễ dàng hiểu, kiểm tra và bảo trì mã. Mô-đun này có thể dẫn đến các chu kỳ phát triển nhanh hơn và quá trình gỡ lỗi nhanh chóng hơn.
  • Tối ưu hóa việc tải mã: Trong các tình huống như tải lười (lazy loading) hoặc nhập động (dynamic imports), thành phần ghép cho phép chỉ tải các thành phần cần thiết cho một tính năng cụ thể. Điều này có thể giảm đáng kể thời gian tải trang ban đầu, cải thiện hiệu suất tổng thể của ứng dụng của bạn.

Như vậy, thành phần ghép là một khái niệm cốt lõi trong ReactJS và là một công cụ mạnh mẽ để xây dựng giao diện người dùng mô-đun, có thể tái sử dụng và dễ bảo trì.

79

Khi nào nên sử dụng useState so với useReducer trong React?

Bạn nên sử dụng useState khi bạn đang quản lý các phần tử trạng thái độc lập không phụ thuộc lẫn nhau. useState là một hook đơn giản cho phép bạn quản lý một biến trạng thái duy nhất. Nó thích hợp cho các trạng thái đơn giản hoặc khi logic kinh doanh không phức tạp.

Ngược lại, useReducer nên được sử dụng khi trạng thái của bạn phức tạp hơn hoặc khi các phần tử trạng thái có sự phụ thuộc lẫn nhau. useReducer cho phép bạn quản lý nhiều hành động khác nhau trong một hàm reducer duy nhất thay vì viết các hàm cập nhật riêng biệt cho mỗi hành động. Điều này làm cho useReducer trở nên lý tưởng cho các ứng dụng lớn hơn với độ phức tạp cao hơn khi quản lý các thay đổi trạng thái giữa các thành phần.

Nếu bạn có nhiều biến trạng thái và muốn có quy tắc cụ thể cho cách cập nhật được xử lý, useReducer sẽ là lựa chọn phù hợp. Nó cũng hữu ích khi trạng thái của bạn bao gồm các đối tượng hoặc mảng và đặc biệt nếu chúng chứa các trạng thái liên quan đến nhau.

Tóm lại, sử dụng useState cho các trạng thái đơn giản và độc lập, và chuyển sang useReducer khi bạn cần quản lý trạng thái phức tạp hơn hoặc khi trạng thái cần được cập nhật dựa trên các trạng thái khác hoặc khi bạn muốn cấu trúc mã nguồn của mình có thêm nhiều tổ chức.

80

Sự khác biệt giữa ComponentContainer trong Redux là gì?

Trong Redux, sự khác biệt chính giữa Component và Container liên quan đến cách chúng tương tác với Redux store và vai trò của chúng trong kiến trúc ứng dụng.

  • Component: Là một phần của API React, Component là một lớp hoặc hàm mô tả một phần của giao diện người dùng (UI) trong ứng dụng React. Component thường được gọi là "presentational components" và chú trọng đến việc hiển thị dữ liệu và cách thức các thứ trông như thế nào. Chúng nhận dữ liệu qua props từ component cha của mình và không trực tiếp tương tác với Redux store. Mục tiêu chính của component là để render HTML, và lý tưởng nhất là chúng nên là stateless, điều này giúp việc viết unit tests trở nên dễ dàng hơn.
  • Container: Là một thuật ngữ không chính thức cho một React component được kết nối (connect) với Redux store. Container biết đến Redux store và có trách nhiệm đăng ký lắng nghe các cập nhật từ Redux state và gửi (dispatch) các hành động. Chúng thường không render các phần tử DOM trực tiếp; thay vào đó, chúng ủy quyền việc render cho các "presentational child components". Container đóng vai trò như một cầu nối giữa trạng thái ứng dụng được quản lý bởi Redux và các thành phần giao diện người dùng, chịu trách nhiệm trích xuất trạng thái cần thiết từ Redux store và truyền nó xuống cho các component để hiển thị.

Tóm lại, Component trong Redux chủ yếu tập trung vào việc hiển thị dữ liệu và cách thức giao diện người dùng trông như thế nào, trong khi Container tập trung vào việc quản lý trạng thái và logic ứng dụng, bao gồm việc tương tác với Redux store để lấy và cập nhật dữ liệu.

81

Bạn sẽ sử dụng flushSync trong ReactJS khi nào?

Bạn sẽ sử dụng flushSync trong ReactJS trong các trường hợp cụ thể khi bạn cần cập nhật giao diện người dùng (UI) ngay lập tức và không muốn chờ đợi cho đến khi React cập nhật DOM theo cơ chế batch mặc định của nó. flushSync là một hàm được giới thiệu trong React 18, cho phép bạn buộc React phải xử lý các cập nhật bên trong callback của nó một cách đồng bộ trước khi tiếp tục với phần còn lại của vòng lặp sự kiện JavaScript.

Dưới đây là một số trường hợp cụ thể mà việc sử dụng flushSync có thể hữu ích:

  1. Yêu cầu Phản Hồi Ngay Lập Tức: Trong các tình huống mà việc cung cấp phản hồi ngay lập tức cho người dùng là quan trọng, ví dụ như khi hiển thị trạng thái "Đang gửi..." ngay sau khi người dùng nhấn nút gửi.
  2. Xử Lý Phụ Thuộc Trạng Thái Phức Tạp: Khi bạn đang xử lý logic trạng thái phức tạp mà các dòng mã tiếp theo phụ thuộc vào trạng thái đã được cập nhật.
  3. Tích Hợp với Thư Viện Bên Ngoài: Khi sử dụng các thư viện bên ngoài không phải của React mà cần DOM được cập nhật ngay lập tức.

Tuy nhiên, cần lưu ý rằng việc sử dụng flushSync có thể ảnh hưởng đến hiệu suất nếu sử dụng quá thường xuyên, vì nó bỏ qua cơ chế batch mặc định của React, có thể dẫn đến việc tăng số lần re-render không cần thiết. Do đó, flushSync nên được sử dụng một cách cẩn thận và chỉ trong những trường hợp thực sự cần thiết.

82

Cách sử dụng React.memo() như thế nào?

React.memo() là một higher order component (HOC) được sử dụng để ngăn chặn việc render lại không cần thiết của component. Nó cho phép bạn tối ưu hóa hiệu suất của các functional component bằng cách ghi nhớ kết quả render cuối cùng và chỉ re-render khi props thay đổi.

Để sử dụng React.memo(), bạn bọc component của mình với React.memo() như sau:

javascript
const MyComponent = React.memo(function MyComponent(props) {
  // Component sẽ chỉ re-render nếu props thay đổi
});

Khi một component được bọc bởi React.memo(), React sẽ kiểm tra xem props của component có thay đổi giữa các lần render hay không. Nếu không có sự thay đổi nào, React sẽ sử dụng lại kết quả render trước đó thay vì tạo ra một kết quả mới.

Trong trường hợp bạn muốn tùy chỉnh việc so sánh props, bạn có thể truyền vào một hàm so sánh tùy chỉnh như tham số thứ hai cho React.memo():

javascript
function areEqual(prevProps, nextProps) {
  // Trả về true nếu props trước và sau không thay đổi
  // Trả về false nếu props có sự thay đổi và cần re-render
}

export default React.memo(MyComponent, areEqual);

Hãy nhớ rằng React.memo() chỉ nên được sử dụng khi bạn xác định được rằng việc re-render là không cần thiết và nó có thể cải thiện hiệu suất của ứng dụng. Tránh sử dụng React.memo() một cách không cần thiết vì nó có thể dẫn đến việc tăng thời gian CPU và giảm hiệu suất nếu việc so sánh props quá phức tạp hoặc không cần thiết.

83

Một custom hook trong React có thể trả về JSX không?

Một custom hook trong React không nên trả về JSX. Custom hook được thiết kế để tái sử dụng logic, không phải để xử lý UI hay trả về các phần tử giao diện. Việc bao gồm JSX trong một custom hook có thể dẫn đến các vấn đề về hiệu suất và làm cho logic khó tái sử dụng trong các bối cảnh khác nhau.

Mặc dù không có quy định cứng rắn cấm việc trả về JSX từ một custom hook, nhưng điều này được coi là một anti-pattern. Custom hook nên tập trung vào việc cung cấp logic và trạng thái, và để cho các component sử dụng hook đó quyết định cách hiển thị UI dựa trên dữ liệu hoặc trạng thái được trả về từ hook.

Ví dụ, thay vì trả về JSX, một custom hook có thể trả về dữ liệu hoặc trạng thái và các hàm để tương tác với dữ liệu đó. Sau đó, component sử dụng hook có thể sử dụng dữ liệu và hàm được trả về để tạo ra JSX phù hợp.

Tóm lại, mặc dù kỹ thuật lập trình trong React không cấm việc một custom hook trả về JSX, nhưng theo các nguyên tắc và phong cách lập trình idiomatic trong React, custom hook nên được sử dụng để chia sẻ logic, không phải để chia sẻ phần tử giao diện.

84

Sự khác biệt giữa ElementComponent trong React là gì?

Trong React, Element và Component là hai khái niệm cơ bản nhưng khác biệt.

  1. Element:

    • Element là một đối tượng đơn giản mô tả những gì bạn muốn hiển thị trên màn hình dưới dạng các nút DOM hoặc các component khác.
    • Element có thể chứa các Element khác trong props của chúng.
    • Tạo một React element là rẻ, và một khi element được tạo ra, nó không bao giờ bị thay đổi.
    • Element là một đại diện không thể thay đổi của một nút DOM hoặc một Component trong cây UI của React.
  2. Component:

    • Component có thể được khai báo theo nhiều cách khác nhau. Nó có thể là một lớp với phương thức render(). Hoặc, trong trường hợp đơn giản, nó có thể được định nghĩa như một hàm.
    • Component nhận props làm đầu vào và trả về một cây JSX làm đầu ra.
    • Component là một phần của mã có thể tái sử dụng, bao gồm các Element và có thể chứa trạng thái bên trong.
    • Component có thể có các phương thức và trạng thái, hỗ trợ vòng đời React và có thể tái sử dụng.

Tóm lại, Element là một đối tượng đơn giản mô tả những gì bạn muốn hiển thị và là đơn vị cấu trúc nhỏ nhất trong React, trong khi Component là một khối xây dựng có thể tái sử dụng, có thể chứa các Element và logic bên trong. Component là cách bạn tạo ra các phần tương tác và phức tạp của UI bằng cách kết hợp các Element với nhau.

85

Làm thế nào để truyền dữ liệu từ component con sang component cha trong React?

Để truyền dữ liệu từ component con sang component cha trong React, bạn thường sử dụng một hàm callback được định nghĩa trong component cha và sau đó truyền hàm này xuống component con dưới dạng props. Khi cần truyền dữ liệu từ con lên cha, component con sẽ gọi hàm callback này và truyền dữ liệu làm đối số.

Cụ thể, bạn có thể thực hiện các bước sau:

  1. Trong component cha, tạo một hàm callback để cập nhật trạng thái (state) hoặc xử lý dữ liệu nhận được từ component con.
  2. Truyền hàm callback này xuống component con thông qua props.
  3. Trong component con, khi có sự kiện hoặc dữ liệu cần truyền lên cha, gọi hàm callback đã được truyền xuống và truyền dữ liệu cần thiết làm đối số cho hàm này.

Ví dụ, nếu bạn có một hàm handleData trong component cha và muốn truyền dữ liệu từ component con, bạn có thể làm như sau:

javascript
// Trong component cha
class ParentComponent extends React.Component {
  handleData = (dataFromChild) => {
    // Xử lý dữ liệu nhận được từ con ở đây
  }

  render() {
    return <ChildComponent sendData={this.handleData} />;
  }
}

// Trong component con
class ChildComponent extends React.Component {
  someFunction = () => {
    const data = 'Dữ liệu cần truyền';
    this.props.sendData(data);
  }

  render() {
    return <button onClick={this.someFunction}>Gửi Dữ liệu</button>;
  }
}

Trong ví dụ trên, khi sự kiện click xảy ra trong ChildComponent, hàm someFunction sẽ được gọi và dữ liệu sẽ được truyền lên ParentComponent thông qua hàm handleData.

86

Làm thế nào để truy cập vào nút DOM trong một React component?

ReactDOM cung cấp cho bạn phương thức ReactDOM.findDOMNode(param) để tìm đối tượng Node tương ứng với tham số của phương thức.

Bên trong Class Component nếu bạn gọi phương thức ReactDOM.findDOMNode(this), nó sẽ trả về cho bạn nút gốc (Root Node) của mô hình DOM. Ví dụ:

js
// File: findDOMNode-example.jsx

class Fruits extends React.Component {
  doFind() {
    // Find root Node of this Component
    var node = ReactDOM.findDOMNode(this);
    node.style.border = "1px solid red";
  }
  render() {
    return (
      <ul>
        <li>Apple</li>
        <li>Apricot</li>
        <li>Banana</li>
        <li>
          <button onClick={() => this.doFind()}>Find Root Node</button>
        </li>
      </ul>
    );
  }
}

// Render
ReactDOM.render(<Fruits />, document.getElementById("fruits1"));
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />

    <title>ReactJS findDOMNode()</title>
    <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
    <style>
      #fruits1 {
        border: 1px solid blue;
        padding: 5px;
        margin-top: 20px;
      }
    </style>
  </head>
  <body>
    <h3>Example: findDOMNode(this)</h3>
    <a href="">Reset</a>

    <div id="fruits1"></div>

    <script src="findDOMNode-example.jsx" type="text/babel"></script>
  </body>
</html>

Kết quả:

findDOMNode trong Reactjs
87

Sự khác biệt giữa FlowPropTypes trong React là gì?

Flow và PropTypes trong React đều là công cụ được sử dụng để kiểm tra kiểu dữ liệu của props trong các component React, nhưng chúng có những khác biệt cơ bản về cách thức hoạt động và mục đích sử dụng:

Flow

  • Flow là một trình kiểm tra kiểu dữ liệu tĩnh cho JavaScript được phát triển bởi Facebook. Nó được sử dụng để kiểm tra kiểu dữ liệu trong toàn bộ mã nguồn, không chỉ trong React components.
  • Flow cung cấp kiểm tra kiểu dữ liệu tĩnh, nghĩa là kiểm tra kiểu dữ liệu được thực hiện tại thời điểm biên dịch mã, trước khi mã được chạy.
  • Flow yêu cầu cấu hình và thêm các annotation kiểu dữ liệu vào mã nguồn để hoạt động. Điều này có thể làm tăng độ phức tạp của mã nguồn nhưng cung cấp kiểm tra kiểu dữ liệu mạnh mẽ và chính xác.
  • Flow không chỉ giới hạn ở kiểm tra kiểu dữ liệu của props mà còn có thể kiểm tra kiểu dữ liệu của biến, hàm, và nhiều cấu trúc dữ liệu khác trong JavaScript.

PropTypes

  • PropTypes là một thư viện kiểm tra kiểu dữ liệu tại thời điểm chạy (runtime) cho props của React components. Nó được tích hợp sẵn trong React và cũng có thể được sử dụng như một thư viện độc lập.
  • PropTypes thực hiện kiểm tra kiểu dữ liệu tại thời điểm chạy, nghĩa là kiểm tra được thực hiện khi ứng dụng đang chạy. Nếu có bất kỳ props nào không phù hợp với kiểu dữ liệu đã định nghĩa, React sẽ hiển thị cảnh báo trong console của trình duyệt.
  • PropTypes cung cấp một cách đơn giản và dễ hiểu để kiểm tra kiểu dữ liệu của props, giúp phát hiện lỗi và ngăn chặn lỗi tiềm ẩn khi phát triển ứng dụng.
  • PropTypes chỉ kiểm tra kiểu dữ liệu của props và không cung cấp kiểm tra kiểu dữ liệu tĩnh cho phần còn lại của mã JavaScript.

So sánh:

  • Kiểm tra kiểu dữ liệu: Flow cung cấp kiểm tra kiểu dữ liệu tĩnh và có thể kiểm tra kiểu dữ liệu trong toàn bộ mã nguồn, trong khi PropTypes chỉ kiểm tra kiểu dữ liệu của props tại thời điểm chạy.
  • Cấu hình và sử dụng: Flow yêu cầu cấu hình và thêm annotation vào mã nguồn, có thể làm tăng độ phức tạp của mã nguồn. PropTypes dễ sử dụng hơn và không yêu cầu cấu hình phức tạp.
  • Phạm vi kiểm tra: Flow có phạm vi kiểm tra rộng hơn, bao gồm không chỉ props mà còn nhiều phần khác của mã JavaScript. PropTypes tập trung vào việc kiểm tra kiểu dữ liệu của props.

Tóm lại, Flow và PropTypes đều hữu ích trong việc kiểm tra kiểu dữ liệu trong React, nhưng chúng phục vụ cho các mục đích và cách thức hoạt động khác nhau. Flow cung cấp kiểm tra kiểu dữ liệu tĩnh mạnh mẽ cho toàn bộ mã nguồn, trong khi PropTypes cung cấp một cách đơn giản để kiểm tra kiểu dữ liệu của props tại thời điểm chạy.

88

Điều gì xảy ra khi bạn gọi setState trong React?

Khi bạn gọi setState trong React, bạn yêu cầu React cập nhật trạng thái (state) của một component và sau đó tái render component đó cùng với các component con của nó (nếu cần). Dưới đây là quy trình chi tiết về những gì xảy ra:

1. Cập nhật Trạng Thái

setState nhận vào một đối tượng hoặc một hàm. Đối tượng này chứa phần của trạng thái mà bạn muốn cập nhật, hoặc hàm này nhận trạng thái hiện tại và props làm đối số và trả về một đối tượng trạng thái mới. React sau đó sẽ lên lịch cập nhật trạng thái của component với thông tin mới.

2. Gọi Phương Thức render

Sau khi trạng thái được cập nhật, React sẽ gọi phương thức render của component để xác định cách giao diện người dùng nên thay đổi dựa trên trạng thái mới. Phương thức render trả về một cây React element (thường được tạo từ JSX).

3. So Sánh Virtual DOM

React sau đó sẽ so sánh cây React element mới với phiên bản trước đó của cây đó (được lưu trữ trong Virtual DOM). Quá trình này được gọi là "diffing". React xác định những phần nào của giao diện người dùng cần thay đổi dựa trên sự khác biệt giữa hai phiên bản của cây.

4. Cập Nhật DOM Thực Tế

Sau khi xác định những thay đổi cần thiết, React sẽ cập nhật DOM thực tế một cách hiệu quả. React chỉ áp dụng những thay đổi tối thiểu cần thiết để đưa DOM thực tế vào trạng thái mới, giúp tối ưu hóa hiệu suất.

5. Gọi Lifecycle Hooks (Nếu Có)

Nếu component sử dụng các phương thức lifecycle như componentDidUpdate, React sẽ gọi các phương thức này sau khi component và các component con của nó đã được tái render và cập nhật trên DOM. Điều này cho phép bạn thực hiện bất kỳ hành động nào sau khi cập nhật, như yêu cầu dữ liệu từ một API.

Lưu Ý

  • Gọi setState là một hành động không đồng bộ. React có thể trì hoãn việc thực thi setState để tối ưu hóa hiệu suất bằng cách nhóm nhiều cập nhật lại với nhau.
  • Bạn không nên dựa vào trạng thái được cập nhật ngay lập tức sau khi gọi setState do tính chất không đồng bộ của nó. Thay vào đó, sử dụng callback trong setState hoặc lifecycle hooks để làm việc với trạng thái sau khi nó được cập nhật.

Quá trình này giúp đảm bảo rằng giao diện người dùng luôn phản ánh trạng thái hiện tại của ứng dụng một cách chính xác và hiệu quả.

89

Trong React, tại sao cần liên kết các event handler với this?

Trong React, việc liên kết các event handler với this là quan trọng vì nó đảm bảo rằng trong phương thức xử lý sự kiện, từ khóa this sẽ tham chiếu đúng đến instance của component. Điều này là cần thiết do cách this hoạt động trong JavaScript và cách React thiết lập các sự kiện.

Lý do cần liên kết this:

  1. Phạm vi của this: Trong JavaScript, phạm vi của từ khóa this phụ thuộc vào cách mà một hàm được gọi chứ không phải là cách nó được viết hoặc khai báo. Điều này có nghĩa là khi bạn truyền một phương thức của component như một event handler, mà không liên kết this, this sẽ không tham chiếu đến component khi phương thức được gọi như một phản ứng với sự kiện.
  2. Không thể truy cập state hoặc props: Khi this không được liên kết đúng cách trong event handler, bạn sẽ không thể truy cập this.state hoặc this.props bên trong phương thức đó, vì this sẽ là undefined hoặc tham chiếu đến một đối tượng không mong muốn.
  3. Không thể sử dụng setState: Tương tự, bạn cũng sẽ không thể gọi this.setState để cập nhật trạng thái của component, vì this không tham chiếu đến instance của component.

Cách liên kết this:

  1. Sử dụng Arrow Functions trong JSX:
    Arrow functions không có this riêng, chúng kế thừa this từ phạm vi bao quanh. Khi sử dụng arrow function để định nghĩa event handler ngay trong JSX, this sẽ tự động tham chiếu đúng đến component.

    jsx
    <button onClick={(e) => this.handleClick(e)}>Click me</button>
  2. Liên kết trong Constructor:
    Một cách khác là liên kết this trong constructor của class component. Điều này đảm bảo rằng this sẽ tham chiếu đúng mỗi khi phương thức được gọi.

    jsx
    constructor(props) {
      super(props);
      this.handleClick = this.handleClick.bind(this);
    }
  3. Sử dụng Class Fields với Arrow Functions:
    Bạn cũng có thể định nghĩa event handler như một class field sử dụng arrow function. Cách này giúp this tự động được liên kết đúng.

    jsx
    handleClick = (e) => {
      console.log(this.props);
    }

Việc liên kết this đúng cách trong các event handler là một bước quan trọng để đảm bảo rằng ứng dụng React của bạn hoạt động như mong đợi, cho phép bạn truy cập và quản lý state, props, và gọi các phương thức khác của component một cách hiệu quả.

90

Làm thế nào để thêm các attributes vào các React components một cách có điều kiện?

Trong React, việc thêm các attributes vào components một cách có điều kiện có thể được thực hiện thông qua việc sử dụng JavaScript expressions trong JSX. Dưới đây là một số cách phổ biến để thực hiện điều này:

Sử dụng Toán Tử Ba Ngôi

Bạn có thể sử dụng toán tử ba ngôi (condition ? true : false) để thêm attributes một cách có điều kiện.

jsx
function MyComponent({ isActive }) {
  return (
    <div className={isActive ? 'active' : ''}>Hello, World!</div>
  );
}

Trong ví dụ trên, class active sẽ chỉ được thêm vào div nếu isActivetrue.

Sử dụng Short-circuit Evaluation

JavaScript cho phép sử dụng short-circuit evaluation để thực hiện các phép toán logic mà không cần đến toán tử ba ngôi. Điều này có thể được sử dụng để thêm attributes.

jsx
function MyComponent({ isActive }) {
  return (
    <div className={isActive && 'active'}>Hello, World!</div>
  );
}

Trong ví dụ trên, nếu isActivetrue, className sẽ là active. Nếu isActivefalse, JavaScript sẽ trả về false và React sẽ bỏ qua attribute này.

Sử dụng Spread Operator để Thêm Props Có Điều Kiện

Bạn cũng có thể sử dụng spread operator (...) để thêm props một cách có điều kiện vào một component.

jsx
function MyComponent({ isActive }) {
  const additionalProps = isActive ? { className: 'active' } : {};

  return (
    <div {...additionalProps}>Hello, World!</div>
  );
}

Trong ví dụ trên, nếu isActivetrue, additionalProps sẽ chứa một đối tượng với classNameactive. Nếu không, nó sẽ là một đối tượng rỗng và không có attribute nào được thêm vào div.

Sử dụng Hàm để Tạo Props

Một cách khác là sử dụng một hàm để tạo ra props dựa trên các điều kiện.

jsx
function getProps(isActive) {
  return isActive ? { className: 'active' } : {};
}

function MyComponent({ isActive }) {
  return (
    <div {...getProps(isActive)}>Hello, World!</div>
  );
}

Trong ví dụ này, hàm getProps trả về một đối tượng props dựa trên giá trị của isActive. Đối tượng này sau đó được truyền vào div sử dụng spread operator.

Các phương pháp trên cho phép bạn thêm các attributes vào React components một cách linh hoạt và có điều kiện, giúp tạo ra các UI động và tùy chỉnh dễ dàng hơn.

91

Trường hợp nào nên dùng shouldComponentUpdate() trong React?

Trong React, shouldComponentUpdate() là một phương thức vòng đời của class component, được sử dụng để cho phép hoặc ngăn chặn việc re-render của component. Bạn nên sử dụng shouldComponentUpdate() trong các trường hợp sau:

1. Tối Ưu Hiệu Suất

Khi bạn muốn tối ưu hóa hiệu suất của ứng dụng bằng cách ngăn chặn các lần re-render không cần thiết. shouldComponentUpdate() cho phép bạn so sánh props hoặc state hiện tại với props hoặc state mới và quyết định xem component có nên cập nhật hay không.

2. So Sánh Props và State

Trong trường hợp component của bạn nhận vào nhiều props hoặc có nhiều state, và bạn biết rằng chỉ một số thay đổi nhất định mới cần dẫn đến việc cập nhật UI. shouldComponentUpdate() có thể được sử dụng để so sánh cụ thể những phần của props hoặc state mà bạn quan tâm.

3. Tránh Re-renders Khi Dữ Liệu Không Thay Đổi

Khi dữ liệu mà component sử dụng không thay đổi, nhưng component vẫn bị re-render do thay đổi ở một phần khác của ứng dụng. Sử dụng shouldComponentUpdate() giúp bạn kiểm soát việc này và ngăn chặn re-render không cần thiết.

4. Khi Sử Dụng PureComponent hoặc React.memo Không Đủ

PureComponentReact.memo cung cấp so sánh nông (shallow comparison) tự động, nhưng nếu bạn cần một so sánh sâu hơn hoặc tùy chỉnh, shouldComponentUpdate() sẽ cần thiết.

5. Phức Tạp Với Việc So Sánh Sâu

Khi bạn có các cấu trúc dữ liệu phức tạp và muốn tránh việc sử dụng các thư viện bên ngoài hoặc logic so sánh sâu, shouldComponentUpdate() có thể giúp bạn thực hiện so sánh một cách tối ưu.

Lưu ý:

  • Sử dụng shouldComponentUpdate() có thể làm phức tạp code nếu không được quản lý cẩn thận.
  • Trong các phiên bản mới của React, bạn có thể sử dụng React.PureComponent hoặc hook React.memo cho function components để có được hiệu suất tương tự mà không cần viết shouldComponentUpdate() thủ công.
  • shouldComponentUpdate() chỉ tồn tại trong class components. Đối với function components, bạn có thể sử dụng hook React.memo cùng với so sánh props tùy chỉnh để đạt được kết quả tương tự.

Tóm lại, shouldComponentUpdate() là một công cụ hữu ích để tối ưu hóa hiệu suất của ứng dụng React bằng cách kiểm soát việc re-render của components dựa trên sự thay đổi của props và state.

92

React Fiber là gì? Giải thích cơ chế hoạt động?

React Fiber là một cơ chế mới cho thuật toán reconciliation của React, là nền tảng của React 16 và các phiên bản sau đó. Fiber là một cải tiến lớn so với thuật toán reconciliation cũ, giúp tối ưu hóa việc render các component và quản lý các tác vụ trong React.

Đặc điểm của React Fiber

  • Incremental Rendering: Fiber cho phép React thực hiện công việc render một cách từng phần nhỏ (incremental), giúp tránh việc block main thread quá lâu và cải thiện trải nghiệm người dùng, đặc biệt là trong các ứng dụng lớn và phức tạp.
  • Task Prioritization: Fiber cung cấp khả năng ưu tiên các tác vụ khác nhau. React có thể tạm dừng và sau đó tiếp tục công việc render dựa trên mức độ ưu tiên của các tác vụ, giúp đảm bảo rằng các tác vụ quan trọng như cập nhật animation và đáp ứng sự kiện được xử lý trước.
  • Concurrency: Fiber giúp React có khả năng hỗ trợ concurrency, cho phép các tác vụ có thể thực hiện đồng thời (concurrent) mà không ảnh hưởng đến hiệu suất chính của ứng dụng.
  • Better Error Handling: Fiber cung cấp cơ chế xử lý lỗi tốt hơn, cho phép các lỗi trong quá trình render có thể được capture và xử lý một cách linh hoạt hơn.

Cách Fiber hoạt động

Fiber giới thiệu khái niệm về "fiber" - một đơn vị công việc nhỏ trong quá trình render. Mỗi fiber đại diện cho một component và công việc cần thực hiện cho component đó. React sẽ duyệt qua cây component và tạo ra các fiber tương ứng, sau đó quản lý việc thực hiện và cập nhật các fiber này theo cách có thể dừng và tiếp tục lại.

Kết luận

React Fiber là một bước tiến quan trọng trong việc cải thiện cơ chế cập nhật và render của React. Nó mang lại khả năng xử lý các tác vụ một cách linh hoạt và hiệu quả, cải thiện hiệu suất và trải nghiệm người dùng, đồng thời giúp các nhà phát triển dễ dàng hơn trong việc xử lý lỗi và quản lý trạng thái ứng dụng.

93

Làm thế nào để thiết lập state với dynamic key name?

Để thiết lập state trong React với dynamic key name, bạn có thể sử dụng cú pháp tính toán tên thuộc tính (computed property names) trong ES6. Điều này cho phép bạn đặt tên key cho state dựa trên giá trị của một biến. Dưới đây là cách bạn có thể làm điều đó:

Sử dụng useState Hook trong Functional Component

Nếu bạn đang sử dụng functional component, bạn có thể sử dụng useState hook để thiết lập state. Để cập nhật state với dynamic key, bạn có thể sử dụng một hàm cập nhật state và truyền vào một object với key được tính toán:

jsx
import React, { useState } from 'react';

function MyComponent() {
  const [state, setState] = useState({});

  function updateState(key, value) {
    setState(prevState => ({
      ...prevState,
      [key]: value
    }));
  }

  // Giả sử bạn muốn cập nhật state với key là giá trị của biến `dynamicKey`
  const dynamicKey = 'myKey';
  const value = 'myValue';

  // Cập nhật state
  updateState(dynamicKey, value);

  // ...
}

Sử dụng this.setState trong Class Component

Nếu bạn đang sử dụng class component, bạn có thể sử dụng phương thức this.setState để cập nhật state. Tương tự như trên, bạn sẽ sử dụng cú pháp tính toán tên thuộc tính:

jsx
import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  updateState(key, value) {
    this.setState({
      [key]: value
    });
  }

  render() {
    // Giả sử bạn muốn cập nhật state với key là giá trị của biến `dynamicKey`
    const dynamicKey = 'myKey';
    const value = 'myValue';

    // Cập nhật state
    this.updateState(dynamicKey, value);

    // ...
  }
}

Trong cả hai ví dụ trên, [key] là cú pháp cho phép bạn sử dụng giá trị của biến key như là tên của key trong object state. Khi bạn gọi hàm updateState hoặc phương thức this.updateState, React sẽ cập nhật state với key và value mà bạn cung cấp.

94

Trong React, refsfindDOMNode() thì phương thức nào được ưu tiên hơn để truy cập các nút DOM hoặc các instance của component?

Trong React, việc sử dụng refs được ưu tiên hơn so với việc sử dụng findDOMNode() để truy cập các nút DOM hoặc các instance của component. Dưới đây là một số lý do chính:

1. Khuyến nghị từ React

React khuyến nghị sử dụng refs thay vì findDOMNode()findDOMNode() có thể sớm bị loại bỏ khỏi các phiên bản tương lai của React. Sử dụng refs là cách tiếp cận chính thức và được khuyến khích để truy cập DOM trong React.

2. Tính linh hoạt và rõ ràng

Refs cung cấp một cách linh hoạt và rõ ràng hơn để truy cập các nút DOM hoặc các instance của component. Bạn có thể gán ref trực tiếp đến một phần tử DOM hoặc component class trong JSX, làm cho mã nguồn dễ đọc và bảo trì hơn.

3. Hỗ trợ Function Components

Trong các phiên bản mới của React, findDOMNode() không hoạt động với function components. Tuy nhiên, bạn có thể sử dụng refs với function components thông qua hook useRef, mở rộng khả năng sử dụng refs trong toàn bộ ứng dụng React của bạn.

4. Tránh sử dụng không cần thiết

findDOMNode() thường được sử dụng khi không có cách nào khác để truy cập DOM, nhưng việc sử dụng nó có thể dẫn đến việc viết mã không tối ưu. Sử dụng refs giúp tránh việc phụ thuộc vào DOM và khuyến khích việc sử dụng dữ liệu và trạng thái để quản lý UI, phù hợp với triết lý của React.

5. Tính tương thích với StrictMode

StrictMode là một công cụ hữu ích trong React giúp phát hiện các vấn đề tiềm ẩn trong ứng dụng. Sử dụng findDOMNode() trong StrictMode sẽ gây ra cảnh báo, trong khi refs hoàn toàn tương thích với StrictMode.

Tóm lại, việc sử dụng refs được ưu tiên hơn findDOMNode() trong React vì nó phù hợp với các khuyến nghị chính thức, cung cấp tính linh hoạt và rõ ràng hơn, hỗ trợ function components, tránh sử dụng không cần thiết và tương thích với StrictMode.

95

Khi nào cần truyền props cho super() trong React?

Trong React, việc truyền props cho super() trong constructor của một class component là cần thiết khi bạn muốn sử dụng this.props trong constructor. Điều này đặc biệt quan trọng nếu bạn cần truy cập đến props để khởi tạo trạng thái hoặc thực hiện các thiết lập ban đầu dựa trên props.

Khi nào cần truyền props cho super():

  1. Khi bạn cần sử dụng this.props trong constructor: Để this.props được định nghĩa trong constructor, bạn cần truyền props đến super(). Nếu không, this.props sẽ là undefined trong phạm vi của constructor.
javascript
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    console.log(this.props); // `props` sẽ được định nghĩa nếu bạn truyền `props` cho `super()`
    this.state = {
      myStateValue: props.initialValue // Sử dụng `props` để khởi tạo state
    };
  }
  // ...
}
  1. Khi bạn không cần sử dụng this.props trong constructor: Nếu bạn không cần truy cập this.props ngay trong constructor, bạn vẫn có thể truyền props cho super() như một thực hành tốt, nhưng nó không bắt buộc. React sẽ tự động thiết lập this.props sau khi constructor được thực thi.

Lưu ý:

  • Dù bạn có truyền props cho super() hay không, this.props sẽ vẫn được định nghĩa và có thể sử dụng bình thường trong các phương thức khác của class, bao gồm render() và các phương thức vòng đời khác.
  • Trong các phiên bản mới của React, việc sử dụng class components đã trở nên ít phổ biến hơn so với function components và hooks. Tuy nhiên, việc hiểu cách sử dụng props trong class components vẫn là kiến thức quan trọng.

Tóm lại, việc truyền props cho super() trong constructor của class component là cần thiết khi bạn muốn sử dụng this.props ngay trong constructor để khởi tạo trạng thái hoặc thực hiện các thiết lập ban đầu dựa trên props.

96

Làm thế nào để sử dụng Polymer trong React?

Polymer và ReactJS là hai thư viện JavaScript phổ biến được sử dụng để xây dựng giao diện người dùng web, nhưng chúng hoạt động dựa trên hai mô hình khác nhau. Polymer tập trung vào việc sử dụng Web Components - một tập hợp các tiêu chuẩn web cho phép tạo ra các thành phần giao diện người dùng tùy chỉnh và tái sử dụng, trong khi ReactJS sử dụng một mô hình dựa trên component JavaScript để xây dựng UI.

Để sử dụng Polymer trong một ứng dụng ReactJS, bạn cần tích hợp Web Components của Polymer vào trong các component React. Dưới đây là một số bước cơ bản để thực hiện điều này:

1. Cài đặt Polymer

Trước tiên, bạn cần cài đặt Polymer và các Web Components mà bạn muốn sử dụng trong ứng dụng React của mình. Bạn có thể cài đặt chúng thông qua npm hoặc bower, tùy thuộc vào cấu hình dự án của bạn.

2. Import Web Components vào Ứng Dụng React

Sau khi đã cài đặt các Web Components của Polymer, bạn cần import chúng vào file JavaScript hoặc TypeScript mà bạn muốn sử dụng chúng. Điều này đảm bảo rằng các Web Components được đăng ký và sẵn sàng để sử dụng trong ứng dụng của bạn.

javascript
import '@polymer/paper-button/paper-button.js';

3. Sử Dụng Web Components trong Component React

Bây giờ bạn có thể sử dụng các Web Components như một phần của UI trong các component React. Bạn chỉ cần sử dụng thẻ tương ứng của Web Component như một phần tử JSX trong render method của component React.

jsx
function MyComponent() {
  return (
    <div>
      <h1>Hello, Polymer!</h1>
      <paper-button raised>Click me</paper-button>
    </div>
  );
}

4. Xử Lý Sự Kiện

Để xử lý sự kiện từ Web Components trong React, bạn có thể sử dụng các thuộc tính sự kiện thông thường của JSX. Ví dụ, nếu bạn muốn xử lý sự kiện click của một paper-button:

jsx
function MyComponent() {
  const handleClick = () => {
    console.log('Button clicked!');
  };

  return (
    <div>
      <h1>Hello, Polymer!</h1>
      <paper-button raised onClick={handleClick}>Click me</paper-button>
    </div>
  );
}

Lưu Ý

  • Đảm bảo rằng các Web Components được tải và đăng ký trước khi ứng dụng React của bạn được mount.
  • Trong một số trường hợp, bạn có thể cần sử dụng ref để truy cập trực tiếp đến Web Component từ React để gọi các phương thức hoặc truy cập các thuộc tính không được hỗ trợ qua props.

Sử dụng Polymer trong ReactJS cho phép bạn tận dụng lợi ích của Web Components, mang lại khả năng tái sử dụng cao và bảo trì dễ dàng cho các thành phần giao diện người dùng của bạn.

97

So sánh Flux với MVC?

Flux và MVC (Model-View-Controller) là hai kiến trúc phần mềm được sử dụng để xây dựng các ứng dụng web. Dưới đây là sự so sánh giữa chúng:

Flux

  • Kiến trúc: Flux là một kiến trúc ứng dụng được phát triển bởi Facebook để sử dụng với React. Nó tập trung vào việc tạo ra một luồng dữ liệu một chiều (unidirectional data flow) trong ứng dụng.
  • Components: Flux chia ứng dụng thành bốn phần chính: Actions, Dispatcher, Stores, và Views (thường là React components).
  • Data Flow: Trong Flux, dữ liệu di chuyển theo một hướng rõ ràng. Actions được tạo ra từ user interactions hoặc từ server, được gửi qua Dispatcher và đến các Stores, nơi trạng thái ứng dụng được quản lý. Các thay đổi trong Stores sau đó sẽ cập nhật Views.
  • Stores: Là nơi lưu trữ và quản lý trạng thái ứng dụng. Mỗi store chịu trách nhiệm cho một phần trạng thái và logic cụ thể của ứng dụng.
  • Dispatcher: Là một trung tâm điều phối, nơi tất cả các actions được gửi đến trước khi đến các stores. Nó đảm bảo rằng actions được xử lý một cách tuần tự.

MVC

  • Kiến trúc: MVC là một kiến trúc phần mềm cổ điển được sử dụng rộng rãi trong phát triển ứng dụng web và desktop. Nó chia ứng dụng thành ba phần chính: Model, View, và Controller.
  • Components:
    • Model: Là nơi định nghĩa cấu trúc dữ liệu của ứng dụng và trực tiếp tương tác với cơ sở dữ liệu hoặc các nguồn dữ liệu khác.
    • View: Là phần hiển thị giao diện người dùng và trình bày dữ liệu đến người dùng.
    • Controller: Là phần điều phối giữa View và Model, xử lý logic ứng dụng, nhận input từ người dùng và quyết định cách hiển thị dữ liệu.
  • Data Flow: Trong MVC, dữ liệu có thể di chuyển theo hai chiều giữa các components. Controller có thể cập nhật Model, và Model cập nhật View, nhưng View cũng có thể gửi user actions trực tiếp đến Controller.

Sự Khác Biệt Chính

  • Luồng Dữ Liệu: Flux sử dụng luồng dữ liệu một chiều, trong khi MVC cho phép dữ liệu di chuyển theo hai chiều giữa các components.
  • Complexity: Flux thường được coi là đơn giản hơn trong việc theo dõi và quản lý dữ liệu do luồng dữ liệu một chiều, trong khi MVC có thể trở nên phức tạp hơn khi ứng dụng lớn lên do sự tương tác hai chiều giữa các components.
  • Stores vs. Models: Trong Flux, Stores chứa cả trạng thái và logic ứng dụng, trong khi trong MVC, Model chỉ chứa trạng thái và logic liên quan đến dữ liệu, và Controller chứa phần lớn logic ứng dụng.

Tóm lại, Flux và MVC đều là những kiến trúc hữu ích với những ưu và nhược điểm riêng, và sự lựa chọn giữa chúng phụ thuộc vào yêu cầu cụ thể của dự án và sở thích của nhóm phát triển. Flux thường được ưa chuộng trong các ứng dụng React do tính tương thích và cách tiếp cận dữ liệu một chiều của nó.

98

Sự khác biệt giữa việc sử dụng constructorgetInitialState trong React là gì?

Trong React, việc khởi tạo trạng thái (state) của một component có thể được thực hiện thông qua constructor hoặc getInitialState. Tuy nhiên, sự khác biệt giữa hai cách này chủ yếu nằm ở phiên bản của React và loại component được sử dụng (class component hay functional component).

Sử dụng constructor

  • Áp dụng cho: Class components.
  • Phiên bản React: ES6 class components (React 0.13 trở lên).
  • Cách sử dụng: Trong một class component, bạn sẽ khởi tạo state bằng cách gán giá trị ban đầu cho this.state trong phương thức constructor của class.
jsx
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      // khởi tạo state ở đây
    };
  }
}
  • Lưu ý: Khi sử dụng constructor để khởi tạo state, bạn cần gọi super(props) trước tiên để đảm bảo rằng class component kế thừa đúng cách từ React.Component.

Sử dụng getInitialState

  • Áp dụng cho: Class components (trước ES6) và Mixins.
  • Phiên bản React: React trước phiên bản 0.13.
  • Cách sử dụng: Trước khi ES6 class được giới thiệu trong React, getInitialState là cách thức khởi tạo state trong React.createClass.
jsx
var MyComponent = React.createClass({
  getInitialState: function() {
    return {
      // khởi tạo state ở đây
    };
  }
});
  • Lưu ý: getInitialState chỉ được sử dụng trong React.createClass, một cú pháp đã bị loại bỏ trong các phiên bản mới của React. Đối với các phiên bản mới, bạn nên sử dụng class components với constructor hoặc functional components với Hooks (ví dụ: useState).

Kết luận

  • Class Components và ES6: Sử dụng constructor để khởi tạo state.
  • Functional Components: Trong React 16.8 trở lên, bạn có thể sử dụng Hooks (useState) để quản lý state trong functional components, thay thế cho cả constructorgetInitialState.
  • React.createClass: getInitialState được sử dụng trong cú pháp cũ React.createClass và không còn được khuyến khích sử dụng trong các phiên bản mới của React.

Như vậy, sự khác biệt chính giữa việc sử dụng constructorgetInitialState nằm ở phiên bản React và loại component được sử dụng.

99

Tại sao chúng ta có cả 2 loại input controlled inputuncontrolled input?

Người phỏng vấn muốn thấy ở đây là một sự hiểu biết vững chắc về khái niệm React cơ bản. Một controlled input nhận 1 prop làm giá trị hiện tại của nó, và 1 prop là 1 callback để thay đổi giá trị đó, nó là một React way

js
<input type="text" value={value} onChange={this.handleChange} />

Một uncontrolled input lưu giá trị của nó bên trong, sử dụng DOM API. Ví dụ dưới đây chúng ta không dùng value và onChange, mà dùng ref():

js
<input type="text" ref={this.textInput} />

Và chúng ta có thể truy xuất giá trị của nó như sau:

js
this.textInput.current.value;

Người phỏng vấn muốn được nghe nhiều thứ hơn có bất kì props nào để sử dụng các uncontrolled component không, có sự khác biệt nào về hiệu suất không? Với cách dùng controlled input thì dữ liệu của bạn (state) và UI (inputs) luôn đồng bộ với nhau, nghĩa là bạn phải cập nhật state của component, điều đó sẽ kích hoạt tiến trình React reconciliation. Còn với cách dùng uncontrolled input thì không cần điều đó, bạn chỉ giữ giá trị input bên trong phần tử DOM của input đó.

100

Tại sao các class method cần phải được bind với một class instance?

Trong React và JavaScript nói chung, các class method cần phải được bind với một class instance để đảm bảo rằng this trong phương thức đó luôn luôn tham chiếu đúng đến instance của class khi phương thức được gọi. Điều này đặc biệt quan trọng khi bạn sử dụng phương thức đó làm callback, ví dụ như trong sự kiện click hoặc trong các hàm bất đồng bộ.

Lý do cần bind:

  1. Đảm bảo this tham chiếu đúng: Trong JavaScript, giá trị của this trong một phương thức phụ thuộc vào cách phương thức đó được gọi. Khi một phương thức class được truyền như một callback mà không được bind, this sẽ không tham chiếu đến instance của class mà thay vào đó là undefined (trong strict mode) hoặc global object (trong non-strict mode), dẫn đến lỗi khi bạn cố gắng truy cập các thuộc tính hoặc phương thức khác của class thông qua this.

  2. Sử dụng trong Callbacks và Event Handlers: Trong React, thường xuyên cần truyền các phương thức class như là callbacks cho các sự kiện, ví dụ như onClick. Để đảm bảo rằng this trong các phương thức đó tham chiếu đúng đến component, bạn cần bind chúng trong constructor hoặc sử dụng các cú pháp khác như class fields syntax hoặc arrow functions trong class properties.

Cách bind:

  1. Trong Constructor:
javascript
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // `this` tham chiếu đúng đến instance của MyComponent
  }
}
  1. Sử dụng Arrow Functions trong Class Properties (không cần bind trong constructor):
javascript
class MyComponent extends React.Component {
  handleClick = () => {
    // `this` tham chiếu đúng đến instance của MyComponent
  }
}
  1. Sử dụng Arrow Functions khi truyền Callback (nhưng cách này có thể gây ra vấn đề về hiệu suất nếu sử dụng trong render method):
javascript
class MyComponent extends React.Component {
  handleClick() {
    // `this` tham chiếu đúng đến instance của MyComponent
  }

  render() {
    return <button onClick={() => this.handleClick()}>Click me</button>;
  }
}

Tóm lại, việc bind các class method với class instance là cần thiết để đảm bảo this tham chiếu đúng trong các tình huống sử dụng method như callbacks hoặc event handlers, giúp tránh các lỗi không mong muốn liên quan đến this không được định nghĩa.

101

Sự khác biệt giữa event handling của HTMLReact là gì?

Sự khác biệt giữa event handling trong HTML thuần và trong React chủ yếu nằm ở cách sự kiện được xử lý và cú pháp được sử dụng. Dưới đây là một số điểm khác biệt chính:

1. Cú pháp

  • HTML thuần: Sự kiện được gắn trực tiếp vào các phần tử HTML thông qua thuộc tính, thường bắt đầu bằng on. Ví dụ: onclick="handleClick()".
  • React: Sự kiện được gắn vào các phần tử JSX bằng cách sử dụng camelCase và không phải là chuỗi. Ví dụ: onClick={handleClick}.

2. Xử lý this

  • HTML thuần: Trong một hàm xử lý sự kiện, this tham chiếu đến phần tử DOM mà sự kiện được gắn vào.
  • React: Trong các class component, this trong các phương thức xử lý sự kiện không tự động tham chiếu đến instance của class, trừ khi bạn rõ ràng bind this trong constructor hoặc sử dụng arrow function.

3. Gọi hàm xử lý sự kiện

  • HTML thuần: Bạn thường gắn một chuỗi chứa lời gọi hàm vào thuộc tính sự kiện, và hàm đó sẽ được gọi khi sự kiện xảy ra.
  • React: Bạn truyền một hàm vào thuộc tính sự kiện. Hàm này sẽ được gọi khi sự kiện xảy ra. React cũng hỗ trợ truyền tham số vào hàm xử lý sự kiện thông qua arrow function hoặc function binding.

4. event Object

  • HTML thuần và React: Cả hai đều cung cấp một đối tượng event cho hàm xử lý sự kiện, chứa thông tin về sự kiện đã xảy ra. Tuy nhiên, React bọc đối tượng event gốc của trình duyệt vào trong một đối tượng SyntheticEvent để đảm bảo tính nhất quán của đối tượng event trên các trình duyệt khác nhau.

5. e.preventDefault()

  • HTML thuần và React: Cả hai đều cho phép bạn gọi e.preventDefault() trong hàm xử lý sự kiện để ngăn chặn hành vi mặc định của trình duyệt. Trong React, bạn thực hiện điều này trong đối tượng SyntheticEvent.

6. Tính nhất quán trên các trình duyệt

  • React: Cung cấp tính nhất quán trên các trình duyệt bằng cách sử dụng SyntheticEvent, trong khi với HTML thuần, bạn có thể cần phải xử lý các sự khác biệt giữa các trình duyệt bằng tay.

Tóm lại, React cung cấp một cách tiếp cận thống nhất và dễ dàng hơn để xử lý sự kiện so với HTML thuần, đồng thời giúp đảm bảo tính nhất quán trên các trình duyệt và dễ dàng quản lý context this trong các phương thức xử lý sự kiện.

102

React khác với AngularJS (1.x) như thế nào?

React và AngularJS (1.x) là hai thư viện/framework phổ biến trong việc xây dựng giao diện người dùng (UI) cho các ứng dụng web, nhưng chúng có những khác biệt cơ bản:

1. Kiến trúc và Phạm vi Ứng dụng

React:

  • Là một thư viện JavaScript được phát triển bởi Facebook, chủ yếu tập trung vào việc xây dựng UI (phần "View" trong mô hình MVC).
  • React sử dụng Virtual DOM để tối ưu hóa việc cập nhật DOM, giúp tăng hiệu suất ứng dụng.
  • React không cung cấp một kiến trúc ứng dụng toàn diện; nó có thể được tích hợp với các thư viện khác như Redux để quản lý trạng thái ứng dụng.

AngularJS (1.x):

  • Là một framework JavaScript toàn diện được phát triển bởi Google, cung cấp một giải pháp "all-in-one" bao gồm data binding, dependency injection, routing, và nhiều tính năng khác.
  • AngularJS sử dụng two-way data binding, tự động đồng bộ hóa dữ liệu giữa model và view.
  • AngularJS cung cấp một kiến trúc ứng dụng hoàn chỉnh, bao gồm cả việc xây dựng các dịch vụ, directive, và các thành phần khác.

2. Cú pháp và Data Binding

React:

  • Sử dụng JSX, một cú pháp mở rộng của JavaScript, cho phép viết HTML trong JavaScript.
  • Hỗ trợ one-way data binding, nghĩa là dữ liệu được truyền từ component cha xuống component con thông qua props.

AngularJS (1.x):

  • Sử dụng HTML với các directive đặc biệt để tạo ra dynamic template.
  • Hỗ trợ two-way data binding, cho phép tự động cập nhật view khi model thay đổi và ngược lại.

3. Component và Directive

React:

  • Xây dựng UI dựa trên component, mỗi component có trạng thái (state) và vòng đời (lifecycle) riêng.
  • Component trong React có thể được tái sử dụng và kết hợp để tạo ra UI phức tạp.

AngularJS (1.x):

  • Sử dụng directive để mở rộng HTML và tạo ra các thành phần tái sử dụng.
  • Cung cấp các directive tích hợp sẵn như ng-model, ng-repeat, ng-if, và cho phép tạo custom directive.

4. Quản lý Trạng thái và Dependency Injection

React:

  • Quản lý trạng thái thông qua state của component hoặc sử dụng các thư viện như Redux.
  • Không có hệ thống dependency injection như AngularJS.

AngularJS (1.x):

  • Quản lý trạng thái thông qua scope và service.
  • Cung cấp một hệ thống dependency injection mạnh mẽ, cho phép quản lý và tái sử dụng các dịch vụ và logic ứng dụng.

5. Cộng đồng và Hỗ trợ

React:

  • Có một cộng đồng lớn và đang phát triển nhanh chóng.
  • Được hỗ trợ bởi nhiều công ty và dự án lớn, với nhiều tài nguyên và công cụ hỗ trợ.

AngularJS (1.x):

  • Cộng đồng lớn và ổn định, nhưng đã giảm sút kể từ khi Angular (phiên bản 2 trở lên) được giới thiệu.
  • AngularJS 1.x vẫn được sử dụng trong nhiều dự án hiện có, nhưng không còn được khuyến nghị cho các dự án mới.

Tóm lại, React và AngularJS (1.x) đều có những ưu và nhược điểm riêng, và sự lựa chọn giữa chúng phụ thuộc vào yêu cầu cụ thể của dự án, kinh nghiệm của đội ngũ phát triển, và các yếu tố khác như kích thước và độ phức tạp của ứng dụng.

103

Làm sao để ngăn các React component re-render?

Trong React, việc ngăn chặn các component không cần thiết phải re-render có thể giúp tối ưu hóa hiệu suất ứng dụng. Dưới đây là một số cách để ngăn chặn re-render:

Sử dụng React.memo cho Function Components

React.memo là một higher order component (HOC) mà nó chỉ cho phép component re-render khi props của nó thay đổi.

javascript
const MyComponent = React.memo(function MyComponent(props) {
  /* render using props */
});

Khi props không thay đổi, MyComponent sẽ không re-render.

Sử dụng shouldComponentUpdate trong Class Components

Phương thức shouldComponentUpdate cho phép bạn quyết định xem một component có nên cập nhật hay không dựa trên sự thay đổi của props hoặc state.

javascript
class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    // return true nếu component cần cập nhật
    // return false nếu không
  }
}

Sử dụng PureComponent

React.PureComponent giống như React.Component nhưng nó thêm một shouldComponentUpdate() với một shallow prop và state comparison.

javascript
class MyComponent extends React.PureComponent {
  // ...
}

Nếu props hoặc state của component không thay đổi, component sẽ không re-render.

Sử dụng Hooks như useMemouseCallback

Khi sử dụng function components, bạn có thể sử dụng hook useMemo để memoize các giá trị và useCallback để memoize các hàm.

javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

Cả hai hook này giúp tránh việc tính toán không cần thiết hoặc tạo ra các hàm mới trong mỗi lần render.

Sử dụng Context một cách cẩn thận

Khi sử dụng React Context, hãy chắc chắn rằng các consumer component không re-render mỗi khi provider value thay đổi. Bạn có thể sử dụng React.memo hoặc useMemo để ngăn chặn điều này.

Tối ưu hóa các Props

Đảm bảo rằng các props bạn truyền vào component không thay đổi giữa các lần render nếu không cần thiết. Điều này bao gồm việc tránh việc truyền các object hoặc array mới được tạo trong mỗi lần render.

Tối ưu hóa State và Context

Khi sử dụng state hoặc context, hãy chia nhỏ nó thành các phần nhỏ hơn nếu có thể để chỉ những phần cần thiết của component được cập nhật khi state hoặc context thay đổi.

Bằng cách áp dụng các phương pháp trên, bạn có thể giảm số lượng re-render không cần thiết và cải thiện hiệu suất của ứng dụng React.

104

Giải thích việc sử dụng React Hook useLayoutEffect?

Hook useLayoutEffect trong React được sử dụng để thực hiện các hiệu ứng có ảnh hưởng đến bố cục (layout) trước khi trình duyệt vẽ (paint) các thay đổi lên màn hình. Nó hoạt động tương tự như useEffect, nhưng với một điểm khác biệt quan trọng: useLayoutEffect được thực thi đồng bộ và sẽ chặn việc vẽ để thực thi mã của mình.

Cụ thể, useLayoutEffect được gọi ngay sau khi React cập nhật DOM (Document Object Model), nhưng trước khi trình duyệt có cơ hội vẽ lại bất kỳ thay đổi nào lên màn hình. Điều này cho phép bạn đọc từ và viết vào DOM, thực hiện các thay đổi hoặc đo lường mà không gây ra hiện tượng nhấp nháy hoặc hiệu ứng không mong muốn do việc vẽ lại.

Một số trường hợp sử dụng phổ biến của useLayoutEffect bao gồm:

  • Đo lường kích thước hoặc vị trí của một phần tử DOM ngay sau khi nó được cập nhật nhưng trước khi trình duyệt vẽ lại, để có thể thực hiện các thay đổi bố cục mà không gây ra hiện tượng nhấp nháy.
  • Thực hiện các thay đổi DOM cần được áp dụng ngay lập tức để đảm bảo trải nghiệm người dùng mượt mà, chẳng hạn như điều chỉnh vị trí cuộn của một phần tử.

Tuy nhiên, do useLayoutEffect chạy đồng bộ và có thể chặn việc vẽ lại của trình duyệt, nó có thể ảnh hưởng đến hiệu suất nếu được sử dụng quá mức. Do đó, bạn nên sử dụng useEffect cho hầu hết các trường hợp và chỉ chuyển sang useLayoutEffect khi cần thiết để xử lý các thay đổi liên quan đến bố cục hoặc khi useEffect không cung cấp kết quả mong muốn.

105

Làm thế nào để force một component re-render với Hooks trong React?

Để buộc một thành phần tái render với Hooks trong React, bạn có thể sử dụng một số phương pháp khác nhau. Một trong những cách phổ biến là sử dụng một biến trạng thái (state variable) để kích hoạt việc tái render. Dưới đây là một số cách tiếp cận:

  1. Sử dụng useState để Tạo Một Biến Trạng Thái Giả Mạo:

Bạn có thể tạo một biến trạng thái không được sử dụng trực tiếp trong render, nhưng thay đổi giá trị của nó sẽ buộc component tái render.
Ví dụ:

 ```javascript
 const [, forceUpdate] = React.useState();
 const reRender = () => forceUpdate({});
 ```

Trong ví dụ trên, forceUpdate là một hàm mà khi được gọi, sẽ buộc component tái render bằng cách cập nhật trạng thái với một đối tượng mới.

  1. Sử dụng useReducer để Tạo Một Hàm Tái Render:

Một cách khác là sử dụng useReducer để tạo một hàm tái render. useReducer thường được sử dụng cho trạng thái phức tạp hơn, nhưng bạn cũng có thể sử dụng nó cho mục đích này.
Ví dụ:

 ```javascript
 const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
 ```

Trong ví dụ này, mỗi lần forceUpdate được gọi, nó sẽ tăng giá trị trạng thái lên 1, từ đó kích hoạt việc tái render.

  1. Sử dụng Custom Hook:

Bạn cũng có thể tạo một custom hook để tái sử dụng logic buộc tái render trong nhiều component.
Ví dụ:

javascript
function useForceUpdate() {
  const [, setTick] = useState(0);
  const update = useCallback(() => {
    setTick((tick) => tick + 1);
  }, []);
  return update;
}
  • Trong ví dụ trên, useForceUpdate là một custom hook mà khi được gọi, sẽ tăng giá trị của biến tick, từ đó buộc component tái render.

Nhớ rằng, việc buộc tái render là một phương pháp nên được sử dụng một cách cẩn thận và chỉ trong những trường hợp cần thiết, vì nó có thể làm giảm hiệu suất của ứng dụng.

106

Hooks có thay thế render props và** higher-order components (HOC)** không?

Hooks không hoàn toàn thay thế render props và higher-order components (HOC), nhưng chúng cung cấp một cách đơn giản hơn để chia sẻ logic giữa các components mà không cần tăng cấp độ lồng nhau trong cây components của bạn. Mặc dù Hooks có thể thay thế HOCs và Render Props trong nhiều trường hợp bằng cách giảm bớt sự phức tạp và lồng nhau, nhưng cả HOCs và Render Props vẫn có những ưu điểm riêng và có thể được sử dụng trong các tình huống cụ thể.

HOC là một mẫu thiết kế độc lập với React, trong khi Hooks là một phần của React. Bạn có thể ghép nối HOCs như các hàm, nhưng Hooks không thể ghép nối. HOC thêm một thành phần khác vào hệ thống phân cấp của components, điều này có thể được kiểm tra trong DevTools.

Tuy nhiên, Hooks giúp tránh được sự phức tạp và khó hiểu khi sử dụng HOCs và Render Props bằng cách cho phép bạn sử dụng trạng thái và các tính năng khác của React mà không cần viết class. Hooks cũng cho phép tạo ra các custom Hooks để chia sẻ logic trạng thái giữa các components một cách dễ dàng.

Như vậy, trong khi Hooks cung cấp một cách tiếp cận mới và đơn giản hơn để chia sẻ logic giữa các components và có thể thay thế HOCs và Render Props trong nhiều trường hợp, cả HOCs và Render Props vẫn có vai trò và ứng dụng riêng trong một số tình huống cụ thể.

107

Những hạn chế nào bạn không nên làm trong hàm render của một component trong React?

Trong React, phương thức render của một component là nơi quan trọng để mô tả cấu trúc UI mà component sẽ hiển thị. Tuy nhiên, có một số hạn chế và thực hành không nên thực hiện trong phương thức render để tránh gặp phải vấn đề về hiệu suất và bảo trì mã nguồn:

  1. Không thực hiện các tác vụ có tác dụng phụ (side effects): Các tác vụ như thực hiện AJAX call, thay đổi DOM trực tiếp, hoặc sử dụng các hàm tạo giá trị ngẫu nhiên như Math.random() không nên được thực hiện trong render vì chúng có thể dẫn đến hành vi không mong muốn và làm cho việc kiểm soát trạng thái trở nên khó khăn.
  2. Không gọi setState trực tiếp: Gọi setState trong render có thể dẫn đến vòng lặp vô tận vì mỗi lần setState được gọi, component sẽ re-render.
  3. Tránh khai báo hàm hoặc đối tượng trong render: Việc khai báo hàm hoặc đối tượng mới trong render sẽ tạo ra một thực thể mới mỗi khi component re-render, dẫn đến việc không thể so sánh props hoặc state hiệu quả và gây ra re-render không cần thiết.
  4. Không sử dụng điều kiện phức tạp: Việc sử dụng quá nhiều điều kiện hoặc vòng lặp phức tạp trong render có thể làm cho mã nguồn trở nên khó đọc và khó bảo trì. Thay vào đó, hãy tách chúng ra thành các hàm hoặc component nhỏ hơn.
  5. Tránh việc sử dụng inline style quá nhiều: Việc sử dụng inline style trực tiếp trong render có thể làm tăng kích thước của DOM và ảnh hưởng đến hiệu suất render. Sử dụng CSS hoặc styled-components là một lựa chọn tốt hơn.
  6. Không thực hiện các phép tính phức tạp hoặc xử lý dữ liệu lớn: Các phép tính phức tạp hoặc xử lý dữ liệu lớn nên được thực hiện ngoài render hoặc sử dụng memoization để giảm thiểu việc tính toán lại không cần thiết.

Tóm lại, phương thức render nên được giữ đơn giản và chỉ chứa mã để mô tả UI. Việc tuân thủ các hạn chế trên giúp đảm bảo rằng component của bạn sẽ hiệu quả về mặt hiệu suất và dễ dàng bảo trì hơn.

108

Làm thế nào để cập nhật status trên một đối tượng lồng nhau với useState()?

Để cập nhật trạng thái trên một đối tượng lồng nhau sử dụng hook useState() trong React, bạn cần tạo một bản sao của đối tượng, cập nhật giá trị cần thiết trong bản sao đó, và sau đó sử dụng hàm cập nhật trạng thái với đối tượng mới. Một cách phổ biến để thực hiện điều này là sử dụng toán tử spread (...) để tạo bản sao và cập nhật giá trị.

Ví dụ, giả sử bạn có trạng thái đối tượng như sau:

javascript
const [user, setUser] = useState({
  name: 'John Doe',
  address: {
    street: '123 Main St',
    city: 'Anytown'
  }
});

Để cập nhật thành phố trong địa chỉ, bạn có thể làm như sau:

javascript
setUser((prevUser) => ({
  ...prevUser,
  address: {
    ...prevUser.address,
    city: 'New City'
  }
}));

Trong ví dụ trên, ...prevUser tạo một bản sao của đối tượng user hiện tại, và ...prevUser.address tạo một bản sao của đối tượng address. Sau đó, bạn cập nhật giá trị của city trong bản sao đó. Cuối cùng, bạn sử dụng hàm setUser với đối tượng mới đã được cập nhật.

Cách tiếp cận này đảm bảo rằng bạn không trực tiếp sửa đổi trạng thái hiện tại (điều này có thể gây ra các vấn đề về hiệu suất và khả năng dự đoán của ứng dụng) và giữ cho trạng thái của ứng dụng không bị thay đổi (immutable), phù hợp với các nguyên tắc của React.

109

Tại sao chúng ta cần 1 thuộc tính key trong React?

Trong React, thuộc tính "key" là một thuộc tính đặc biệt và quan trọng được sử dụng khi render một danh sách các phần tử để giúp React xác định các phần tử nào đã thay đổi, được thêm vào, hoặc bị xóa. Các lý do chính cần sử dụng thuộc tính "key" bao gồm:

1. Tối Ưu Hóa Hiệu Suất

Khi danh sách dữ liệu thay đổi, React sẽ sử dụng thuộc tính "key" để so sánh các phần tử trong danh sách mới với danh sách cũ và xác định nhanh chóng các phần tử nào cần được cập nhật, thêm vào, hoặc xóa bỏ. Điều này giúp tối ưu hóa quá trình cập nhật DOM và cải thiện hiệu suất của ứng dụng.

2. Quản Lý Trạng Thái Component

Trong trường hợp các component có trạng thái nội bộ (state), việc sử dụng "key" giúp React quản lý trạng thái của các component một cách chính xác khi danh sách dữ liệu thay đổi. Nếu không có "key", React có thể sẽ không đúng trong việc tái sử dụng các component, dẫn đến lỗi hoặc hành vi không mong muốn trong UI.

3. Tránh Vấn Đề Với DOM

Khi không sử dụng "key" hoặc sử dụng "key" không đúng cách (ví dụ: sử dụng chỉ số mảng làm "key"), React có thể sẽ không cập nhật DOM một cách chính xác khi dữ liệu thay đổi. Điều này có thể dẫn đến các lỗi UI, như hiển thị dữ liệu sai hoặc không cập nhật UI khi dữ liệu thay đổi.

4. Tái Sử Dụng và Sắp Xếp Component

Khi cần tái sử dụng hoặc sắp xếp lại các component trong danh sách mà không mất trạng thái của chúng, "key" giúp React xác định chính xác các component này để tái sử dụng hoặc sắp xếp mà không cần phải tạo lại từ đầu.

Kết Luận

Thuộc tính "key" là một phần quan trọng trong việc xây dựng các ứng dụng React hiệu quả và hiệu suất cao. Việc sử dụng "key" một cách chính xác giúp đảm bảo rằng React có thể theo dõi và cập nhật danh sách các phần tử một cách chính xác, giúp ứng dụng của bạn hoạt động mượt mà và đáng tin cậy hơn.

110

Khi một ứng dụng React bị render chậm, bạn sẽ làm thế nào để tìm ra nguyên nhân gây ra việc đó?

Một trong những nguyên nhân phổ biến nhất gây ra việc render chậm trong các ứng dụng React là khi các component được re-render không cần thiết. Có hai công cụ được cung cấp bởi React có ích trong những trường hợp sau:

  • React.memo(): Điều này ngăn việc re-render không cần thiết của function component.
  • PureComponent: Điều này ngăn việc re-render không cần thiết của class component.

Cả hai công cụ này đều dựa trên sự so sánh nông (shallow comparison) của các props được truyền vào component — nếu props không thay đổi, thì component sẽ không re-render. Mặc dù cả hai công cụ đều rất hữu ích, nhưng so sánh nông sẽ ảnh hưởng về hiệu suất, vì vậy cả hai đều có thể có tác động tiêu cực đến hiệu suất nếu sử dụng không đúng cách.

React Profiler là gì

Một cách tối ưu hơn đó là chúng ta sử dụng React Profiler, hiệu suất có thể được đo lường trước và sau khi sử dụng các công cụ này để đảm bảo rằng hiệu suất thực sự được cải thiện bằng cách thực hiện một thay đổi nhất định.

111

Ưu điểm của React so với Vuejs là gì?

Ưu điểm của React so với VueJS bao gồm:

1. Cộng đồng lớn và hỗ trợ mạnh mẽ

React được phát triển và duy trì bởi Facebook, có một cộng đồng lớn với hàng nghìn nhà phát triển và công ty sử dụng nó. Điều này đảm bảo rằng React có nhiều tài nguyên học tập, thư viện bổ sung, và hỗ trợ từ cộng đồng.

2. Tích hợp linh hoạt

React có thể dễ dàng tích hợp với các thư viện khác như Redux, MobX, hoặc thậm chí là Vue trong một số trường hợp. Điều này cho phép các nhà phát triển tận dụng sức mạnh của React trong khi vẫn sử dụng các công cụ khác mà họ ưa thích.

3. Tái sử dụng component

React khuyến khích việc phát triển dựa trên component, giúp tái sử dụng code và quản lý trạng thái trở nên dễ dàng hơn. Các component có thể được đóng gói và tái sử dụng trong các dự án khác nhau, giúp tăng tốc độ phát triển và bảo trì.

4. Virtual DOM

React sử dụng Virtual DOM để tối ưu hóa việc cập nhật giao diện người dùng. Khi trạng thái của ứng dụng thay đổi, React sẽ so sánh sự thay đổi trong Virtual DOM với DOM thực tế và chỉ cập nhật những phần cần thiết, giúp tăng hiệu suất.

5. JSX

React sử dụng JSX, một cú pháp mở rộng của JavaScript, cho phép viết HTML trong JavaScript. Điều này giúp việc viết và đọc code trở nên dễ dàng hơn, đặc biệt là khi làm việc với các cấu trúc UI phức tạp.

6. Hỗ trợ từ các công ty lớn

Ngoài Facebook, nhiều công ty lớn khác như Airbnb, Netflix, và Dropbox cũng sử dụng và hỗ trợ React. Điều này không chỉ chứng minh sức mạnh và độ tin cậy của React mà còn đảm bảo rằng nó sẽ tiếp tục được phát triển và cải thiện.

7. Server-side rendering

React hỗ trợ server-side rendering (SSR) thông qua thư viện như Next.js, giúp cải thiện thời gian tải trang và SEO cho các ứng dụng web.

8. React Native

React có thể được sử dụng để phát triển ứng dụng di động với React Native, cho phép chia sẻ logic ứng dụng giữa web và mobile, giảm thời gian và chi phí phát triển.

Tóm lại, mặc dù cả React và VueJS đều có những ưu điểm riêng, React nổi bật với cộng đồng lớn, tích hợp linh hoạt, tái sử dụng component, Virtual DOM, JSX, hỗ trợ từ các công ty lớn, SSR, và khả năng phát triển ứng dụng di động với React Native.

112

Khi nào nên sử dụng forceUpdate trong một React component?

Trong React, forceUpdate() là một phương thức của class component, được sử dụng để buộc một component re-render, bỏ qua phương thức shouldComponentUpdate(). Tuy nhiên, việc sử dụng forceUpdate() thường không được khuyến khích và chỉ nên sử dụng trong một số trường hợp cụ thể:

1. Khi Component Không Sử Dụng State hoặc Props

Nếu component của bạn không phụ thuộc vào state hoặc props để render, và bạn cần cập nhật UI dựa trên sự thay đổi của một số dữ liệu bên ngoài mà React không thể phát hiện, forceUpdate() có thể được sử dụng để buộc component re-render.

2. Khi Sử Dụng Third-party DOM Libraries

Trong trường hợp bạn đang sử dụng một thư viện DOM bên ngoài không phải của React, và thư viện đó thay đổi DOM mà không thông qua React, forceUpdate() có thể được sử dụng để đồng bộ hóa lại với React sau khi thư viện thực hiện thay đổi.

3. Khi Tối Ưu Hóa Hiệu Suất

Trong một số trường hợp hiếm hoi, bạn có thể muốn tối ưu hóa hiệu suất bằng cách bỏ qua việc kiểm tra shouldComponentUpdate(), và forceUpdate() có thể được sử dụng để đạt được điều này. Tuy nhiên, điều này nên được xem xét cẩn thận vì nó có thể dẫn đến việc re-render không cần thiết và làm giảm hiệu suất.

Lưu ý:

  • Sử dụng forceUpdate() có thể dẫn đến việc viết mã không tối ưu và khó bảo trì. Trong hầu hết các trường hợp, việc sử dụng stateprops để quản lý re-render là đủ và được khuyến khích.
  • forceUpdate() không gọi shouldComponentUpdate(), nhưng vẫn gọi các phương thức vòng đời khác như componentWillUpdate(), componentDidUpdate(), và render().
  • Trong function components, không có phương thức tương đương với forceUpdate(). Thay vào đó, bạn có thể sử dụng hook useState hoặc useReducer để buộc re-render.

Tóm lại, forceUpdate() nên được sử dụng một cách thận trọng và chỉ trong những trường hợp cần thiết khi các cơ chế thông thường của React không đáp ứng được yêu cầu của ứng dụng.

113

So sánh redux thunkredux saga?

Redux Thunk và Redux Saga đều là middleware trong Redux được sử dụng để xử lý các tác vụ bất đồng bộ như tương tác với API hoặc thực hiện logic phức tạp trước khi cập nhật state. Tuy nhiên, chúng có những điểm khác biệt cơ bản về cách thức hoạt động và cú pháp.

Redux Thunk

  • Đơn giản và Dễ bắt đầu: Redux Thunk là một middleware đơn giản giúp viết logic bất đồng bộ trong các action creator. Nó cho phép action creator trả về một hàm thay vì một action object. Hàm này có thể thực thi các tác vụ bất đồng bộ và sau đó dispatch một action khi tác vụ hoàn thành.
  • Cú pháp: Sử dụng các hàm JavaScript thông thường, dễ hiểu và áp dụng cho những người đã quen với JavaScript.
  • Kiểm soát: Cung cấp kiểm soát tốt cho các tác vụ bất đồng bộ nhưng có thể trở nên khó quản lý khi ứng dụng phát triển và số lượng tác vụ bất đồng bộ tăng lên.

Redux Saga

  • Mạnh mẽ và linh hoạt: Redux Saga sử dụng ES6 Generator functions để làm cho việc quản lý các tác vụ bất đồng bộ trở nên dễ dàng hơn. Nó cung cấp một cách mạnh mẽ và linh hoạt để xử lý các tác vụ phức tạp, bao gồm các tác vụ bất đồng bộ, chuỗi các tác vụ phụ thuộc lẫn nhau, và hơn thế nữa.
  • Cú pháp: Sử dụng ES6 Generator functions, có thể làm cho code trở nên phức tạp và khó hiểu đối với những người mới làm quen với chúng.
  • Kiểm soát và hiệu suất: Cung cấp khả năng kiểm soát cao đối với các tác vụ bất đồng bộ và cho phép thực hiện các tác vụ nâng cao như debounce, throttle, và race conditions. Tuy nhiên, cú pháp và cách tiếp cận có thể làm tăng độ phức tạp của code.

So sánh:

  • Độ phức tạp: Redux Thunk đơn giản hơn và dễ tiếp cận hơn cho các dự án nhỏ đến trung bình. Redux Saga mạnh mẽ hơn và phù hợp với các ứng dụng lớn và phức tạp với nhiều tác vụ bất đồng bộ và logic phức tạp.
  • Cách tiếp cận: Thunk sử dụng hàm, trong khi Saga sử dụng ES6 Generators để quản lý các tác vụ bất đồng bộ.
  • Khả năng kiểm soát: Saga cung cấp khả năng kiểm soát cao hơn đối với các tác vụ bất đồng bộ và cho phép thực hiện các tác vụ nâng cao một cách dễ dàng.

Tóm lại, lựa chọn giữa Redux Thunk và Redux Saga phụ thuộc vào độ phức tạp của ứng dụng, sở thích cá nhân và kinh nghiệm làm việc với JavaScript của bạn. Thunk thường được ưa chuộng cho các dự án nhỏ hơn và ít phức tạp, trong khi Saga là lựa chọn tốt cho các ứng dụng lớn hơn và yêu cầu nhiều tác vụ bất đồng bộ phức tạp.

114

Làm thế nào để tạo Props Proxy cho HOC component?

Trong React, Props Proxy là một kỹ thuật trong Higher-Order Components (HOC) mà thông qua đó HOC có thể thay đổi, thêm, hoặc loại bỏ props trước khi chúng được truyền đến Wrapped Component (component được bọc bởi HOC). Đây là một cách để tùy chỉnh hoặc thay đổi hành vi của một component mà không cần sửa đổi mã nguồn của chính component đó.

Cách tạo Props Proxy cho HOC:

Để tạo một Props Proxy cho một HOC, bạn sẽ tạo một function mà nhận vào một component và trả về một component mới. Trong function này, bạn có thể thay đổi props trước khi chúng được truyền đến Wrapped Component.

Dưới đây là một ví dụ về cách tạo một Props Proxy HOC:

javascript
import React from 'react';

// Đây là HOC Props Proxy
function withPropsProxy(WrappedComponent) {
  // Trả về một component mới
  return class extends React.Component {
    render() {
      // Tạo một bản sao của props
      const newProps = {
        ...this.props,
        // Thêm, thay đổi hoặc loại bỏ các props tại đây
        extraProp: 'This is an extra prop!'
      };

      // Truyền newProps đến WrappedComponent
      return <WrappedComponent {...newProps} />;
    }
  };
}

// Sử dụng HOC với một component bất kỳ
const EnhancedComponent = withPropsProxy(MyComponent);

Trong ví dụ trên, withPropsProxy là một HOC mà tạo ra một Props Proxy. Nó nhận vào WrappedComponent, tạo một bản sao của props hiện tại, thêm một extraProp, và sau đó truyền newProps đến WrappedComponent.

Lưu ý khi sử dụng Props Proxy HOC:

  • Đảm bảo rằng bạn không vô tình ghi đè lên các props quan trọng mà WrappedComponent cần để hoạt động đúng đắn.
  • Sử dụng Props Proxy có thể làm tăng độ phức tạp của component tree và có thể ảnh hưởng đến hiệu suất nếu không được sử dụng một cách cẩn thận.
  • Props Proxy HOC có thể được kết hợp với các kỹ thuật HOC khác như Inheritance Inversion để tạo ra các HOC mạnh mẽ và linh hoạt hơn.

Tóm lại, Props Proxy là một kỹ thuật hữu ích trong việc tạo ra các HOC để tùy chỉnh hành vi của các component mà không cần sửa đổi trực tiếp mã nguồn của chúng.

115

Thứ tự của các hook useInsertionEffect, useEffectuseLayoutEffect trong quá trình tạo ra component là gì?

Trong quá trình tạo ra và cập nhật một component trong React, thứ tự thực thi của các hook useInsertionEffect, useEffect và useLayoutEffect được xác định như sau:

  1. useInsertionEffect: Hook này chạy đồng bộ trước khi trình duyệt thực hiện việc vẽ (paint), cho phép chèn hoặc thay đổi các style trước khi chúng được phản ánh trên màn hình. Điều này đặc biệt hữu ích khi làm việc với các thư viện CSS-in-JS, đảm bảo rằng không có sự chớp nháy hoặc chuyển động giật cục khi style được áp dụng.
  2. useLayoutEffect: Hook này chạy đồng bộ ngay sau khi React thực hiện tất cả các thay đổi DOM cần thiết nhưng ngay trước khi trình duyệt vẽ lại màn hình. Nó có cùng API và cú pháp tương tự như useEffect, nhưng được thiết kế để xử lý các side effects liên quan đến layout hoặc cần cập nhật DOM ngay lập tức trước khi màn hình được vẽ lại.
  3. useEffect: Hook này chạy một cách bất đồng bộ sau khi trình duyệt đã vẽ xong màn hình. Nó thường được sử dụng để xử lý các side effects không liên quan trực tiếp đến việc vẽ giao diện, như fetching dữ liệu, thiết lập subscriptions, hoặc tương tác với DOM mà không cần cập nhật ngay lập tức.

Tóm lại, thứ tự thực thi của các hook trong quá trình tạo ra và cập nhật component là: useInsertionEffect chạy trước, tiếp theo là useLayoutEffect, và cuối cùng là useEffect. Sự phân biệt này giúp đảm bảo rằng các thay đổi về style được áp dụng trước khi màn hình được vẽ lại, các thay đổi về layout được xử lý trước khi người dùng nhìn thấy giao diện, và các side effects không ảnh hưởng đến việc vẽ giao diện được xử lý sau cùng.

116

Khi nào bạn muốn sử dụng useLayoutEffect thay thế cho useEffect?

Bạn sẽ muốn tránh sử dụng useEffect và sử dụng useLayoutEffect thay thế khi bạn cần thực hiện các thay đổi trên DOM hoặc cần thực hiện các phép đo DOM trước khi trình duyệt cập nhật màn hình (repaint). Điều này giúp tránh tình trạng nhấp nháy hoặc không đồng bộ về giao diện người dùng mà người dùng có thể nhận thấy nếu bạn sử dụng useEffect.

useLayoutEffect chạy đồng bộ ngay sau khi React thực hiện các thay đổi DOM nhưng trước khi trình duyệt cập nhật màn hình. Điều này có nghĩa là bạn có thể sử dụng useLayoutEffect để đọc từ và viết vào DOM mà không gây ra hiện tượng nhấp nháy hoặc hiển thị trạng thái không mong muốn trên giao diện người dùng.

Một ví dụ cụ thể khi bạn muốn sử dụng useLayoutEffect thay vì useEffect là khi bạn cần thực hiện các hoạt động như cuộn tự động đến một vị trí cụ thể trong một danh sách hoặc điều chỉnh kích thước của một phần tử dựa trên kích thước của phần tử khác. Trong những trường hợp này, việc sử dụng useLayoutEffect giúp đảm bảo rằng các thay đổi được thực hiện một cách mượt mà và không gây ra hiện tượng nhấp nháy hoặc hiển thị không đúng trên giao diện người dùng trước khi trình duyệt cập nhật màn hình.