React API cấp cao nhất

Để bắt đầu tìm hiểu về bộ thư viện React thì React package chính là điểm xuất phát. Nếu bạn load React trực tiếp từ một thẻ script, những API ở cấp cao nhất sẽ có sẵn trên React ‘global’. Nếu bạn dùng ES6 và npm, bạn có dùng câu lệnh import React from 'react'. Nếu bạn dùng ES5 và npm, bạn có thể khai báo var React = require('react').

Giới thiệu chung

Components

React components dùng để chia UI thành những thành phần nhỏ độc lập, có tính tái sử dụng, và xem xét chúng như một mảnh riêng biệt. Bạn có thể định nghĩa React components bằng cách kế thừa các lớp con của React: React.Component hay React.PureComponent.

Nếu bạn không sử dụng classes trong ES6, thì có thể dùng create-react-class module thay thế. Xem thêm Không sử dụng ES6 trong React để hiểu rõ hơn.

Các React component cũng có thể được định nghĩa như là những function được bao bọc bởi:

Tạo React Elements

Chúng tôi khuyến khích bạn nên sử dụng JSX để cấu trúc phần UI (nó tương tự như HTML vậy). Mỗi JSX element được tạo ra bằng cách gọi hàm React.createElement(). Thông thường, bạn sẽ không cần gọi các “phương thức” (method) sau nếu bạn đang sử dụng JSX.

Xem thêm Không sử dụng JSX trong React để hiểu rõ hơn.

Việc chuyển đổi các element

React cung cấp nhiều API để thao tác với các React element:

Fragments

React cũng cung cấp một component cho việc render nhiều elements mà không cần thành phần bao bọc (giống như bạn phải có 1 thẻ div để bọc các thành phần con trong HTML).

Refs

Suspense

Suspense giúp cho components “chờ” để xử lý một việc gì đó trước khi rendering. Hiện tại, Suspense chỉ hỗ trợ trong một trường hợp duy nhất: loading components linh hoạt với React.lazy. Trong tương lai, nó sẽ hỗ trợ các trường hợp khác như fetch dữ liệu từ bên ngoài (API, Socket, …).

Hooks

Hooks là một sự bổ sung từ phiên bản React 16.8. Chúng giúp cho bạn có thể sử dụng state và những features khác của React mà không cần phải viết một class. Hooks có hẳn một chương tài liệu chuyên biệt và một bộ API riêng biệt:


Reference

React.Component

React.Component là lớp cơ sở cho các React components khi ta định nghĩa một component với ES6 classes:

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Xem thêm React.Component API Reference để tìm hiểu thêm danh sách các phương thức và thuộc tính liên quan đến lớp React.Component cơ sở.


React.PureComponent

React.PureComponent cũng giống như React.Component. Điểm khác biệt giữa chúng là React.Component không thực hiện hàm shouldComponentUpdate(), trong khi đó React.PureComponent thì có, nó sẽ so sánh nông (shallow) tất cả các thuộc tính của props và state để quyết định xem component này có cần update hay không.

Nếu như những React components của bạn gọi đến render() function để biểu diễn cùng kết quả với cùng props và state, bạn có thể sử dụng React.PureComponent để tăng hiệu suất cho ứng dụng trong một số trường hợp.

Lưu ý

Phương thức shouldComponentUpdate() của React.PureComponent chỉ so sánh nông (shallow) các đối tượng. Nếu chúng có cấu trúc dữ liệu phức tạp, có thể xảy ra trường hợp bỏ sót nếu sự khác biệt nằm sâu bên trong. Chỉ kế thừa PureComponent khi bạn có props và state đơn giản, hoặc sử dụng forceUpdate() nếu bạn chắc chắc rằng cấu trúc dữ liệu đã bị thay đổi. Hoặc, bạn có thể sử dụng immutable objects để dễ dàng so sánh nhanh các dữ liệu lồng nhau.

Hơn nữa, “phương thức” (method) shouldComponentUpdate() của React.PureComponent bỏ qua việc cập nhật prop cho toàn bộ các component con. Nên hãy chắc chắn rằng các component con cũng là “pure”.


React.memo

const MyComponent = React.memo(function MyComponent(props) {
  /* render using props */
});

React.memo là một component bậc cao (higher order component). Nó tương tự như React.PureComponent nhưng là dạng function components chứ không phải là classes.

Nếu function component của bạn biểu diễn cùng kết quả với cùng props, bạn có thể gói chúng lại và gọi đến React.memo để tăng hiệu năng trong một số trường hợp bằng cách ghi nhớ kết quả. Điều này có nghĩa là React sẽ bỏ qua việc render component, và sử dụng lại kết quả đã render lần cuối cùng.

Mặc định nó sẽ chỉ so sánh nông (shallow) các đối tượng phức tạp bên trong đối tượng props. Nếu bạn muốn kiểm soát toàn bộ việc so sánh, bạn cũng có thể cung cấp một hàm so sánh tuỳ chỉnh ở đối số thứ hai.

function MyComponent(props) {
  /* render using props */
}
function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}
export default React.memo(MyComponent, areEqual);

Phương thức này tồn tại như một cách tối ưu hiệu suất (performance optimization). Đừng dựa vào nó để “ngăn” việc render component, vì rất dễ gây ra lỗi.

Lưu ý

Không giống như method shouldComponentUpdate() trong class components, hàm areEqual trả về true nếu các props bằng nhau và trả về false nếu các props không bằng nhau. Nó ngược lại với hàm shouldComponentUpdate.


createElement()

React.createElement(
  type,
  [props],
  [...children]
)

Tạo và trả về một React element mới theo kiểu truyền vào. Đối số type có thể là tên của thẻ dạng ký tự (ví dụ như 'div' hay 'span'), một kiểu React component (class hay function), hoặc là một loại React fragment.

Mã được viết bằng JSX sẽ được chuyển đổi để sử dụng React.createElement(). Thông thường, bạn sẽ không cần gọi trực tiếp React.createElement() nếu bạn sử dụng JSX. Xem thêm Không sử dụng JSX trong React để hiểu rõ hơn.


cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

Sao chép và trả về một React element mới bằng cách sử dụng element làm điểm bắt đầu. Element kết quả có các props của element gốc kết hợp nông (shallowly) với các props mới. Thành phần con mới sẽ thay thế thành phần con hiện có. keyref từ element gốc sẽ được giữ nguyên.

React.cloneElement() gần như là tương đương với:

<element.type {...element.props} {...props}>{children}</element.type>

Tuy nhiên, nó cũng sẽ giữ lại các ref. Điều này có nghĩa rằng nếu bạn có một thành phần con cùng với một ref trên nó, bạn đã vô tình đánh cắp nó từ các thành phần cha. Bạn sẽ nhận được cùng ref đính kèm trên element mới của bạn.

API này được giới thiệu như là một giải pháp thay thế cho React.addons.cloneWithProps() không được dùng nữa.


createFactory()

React.createFactory(type)

<<<<<<< HEAD Trả về một hàm tạo ra các React element theo kiểu truyền vào. Giống như React.createElement(), đối số type có thể là tên của thẻ dạng ký tự (ví dụ như 'div' hay 'span'), một kiểu React component (class hay function), hoặc là một loại React fragment. ======= Return a function that produces React elements of a given type. Like React.createElement(), the type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type.

6bc6e7b1411d4befc3ecfbe45b898ca474116020

Hàm này được coi là di sản, và chúng tôi khuyến khích bạn sử dụng JSX hoặc sử dụng trực tiếp React.createElement().

Thông thường, bạn sẽ không gọi trực tiếp React.createFactory() nếu bạn sử dụng JSX. Xem thêm Không sử dụng JSX trong React để tìm hiểu thêm.


isValidElement()

React.isValidElement(object)

Để xác thực đối tượng là một React element. Trả về true hoặc false.


React.Children

React.Children cung cấp các tiện ích để tương tác với “cấu trúc dữ liệu ẩn” (opaque data structure) this.props.children.

React.Children.map

React.Children.map(children, function[(thisArg)])

Gọi ngay một hàm trên mỗi thành phần con, bên trong là children cùng với this được gáng cho thisArg. Nếu children là một mảng nó sẽ duyệt mảng đó và hàm sẽ được thực thi cho mỗi thành phần con trong mảng. Nếu childrennull hoặc undefined, phương thức này sẽ trả về null hoặc undefined thay vì là một mảng.

Lưu ý

Nếu children là một Fragment nó sẽ được xem như là một thành phần con đơn lẻ và không đi qua.

React.Children.forEach

React.Children.forEach(children, function[(thisArg)])

Giống như React.Children.map() nhưng không trả về một mảng.

React.Children.count

React.Children.count(children)

Trả về tổng số lượng các component trong children, bằng đúng với số lần hàm callback sẽ được gọi trong map hay forEach.

React.Children.only

React.Children.only(children)

Xác thực rằng children có duy nhất một thành phần con (một React element) và trả về element đó. Nếu không phương thức này sẽ đưa ra lỗi.

Lưu ý:

React.Children.only() không cho phép trả về giá trị của React.Children.map() bởi vì nó là một mảng thay vì là một React element.

React.Children.toArray

React.Children.toArray(children)

Trả về “cấu trúc dữ liệu ẩn” (opaque data structure) của children dưới dạng mảng một chiều với “khoá” (keys) được gắn cho mỗi “thành phần con” (child). Điều này sẽ hữu ích nếu bạn muốn vận dụng “bộ sưu tập” (collections) trong phương thức render của bạn, đặt biệt nếu bạn muốn sắp xếp lại hoặc cắt this.props.children trước khi trả về.

Lưu ý:

React.Children.toArray() thay đổi các khoá để giữ nguyên ngữ nghĩa của các mảng lồng nhau khi làm phẳng “flattening” danh sách của children. Nghĩa là, tiền tố toArray mỗi “khoá” (key) trong mảng được trả về sao cho mỗi phần thử khoá đặt trong mảng đầu vào có chứa nó.


React.Fragment

React.Fragment component cho phép bạn trả về nhiều “phần tử” (elements) trong một phương thức render() mà không cần tạo “phần tử” (element) DOM:

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}

Bạn cũng có thể sử dụng nó với cú pháp ngắn gọn sau đây <></>. Để có thêm thông tin, xem thêm React v16.2.0: Cải thiện hỗ trợ cho Fragments (Improved Support for Fragments).

React.createRef

React.createRef tạo ra một ref có thể được gắn vào các phần tử (elements) của React thông qua “thuộc tính” (attribute) ref.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  render() {
    return <input type="text" ref={this.inputRef} />;
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }
}

React.forwardRef

React.forwardRef tạo ra một “thành phần” (component) React, giúp “chuyển tiếp” (forwards) “thuộc tính” (attribute) ref mà nó nhận được cho các thành phần khác bên dưới “cây” (tree). Kỹ thuật này không thật sự phổ biến nhưng lại đặc biệt hữu ích trong hai tình huống sau:

React.forwardRef chấp nhận một “hàm biểu diễn” (rendering function) là một đối số. React sẽ gọi đến hàm này với hai đối số là propsref. Hàm này nên trả về một “nút” (node) React.

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Trong ví dụ trên, React chuyển một ref truyền vào “phần tử” (element) <FancyButton ref={ref}> ở đối số thứ hai cho “hàm biểu diễn” (rendering function) bên trong lệnh gọi React.forwardRef. “Hàm biểu diễn” (rendering function) này chuyển ref cho “phần tử” (element) <button ref={ref}>.

Kết quả là, sau khi React đính kèm ref, ref.current sẽ trỏ trực tiếp tới “phần tử” (element) “đối tượng” (instance) <button> DOM.

Để có thểm thông tin, xem thêm “chuyển tiếp” refs (forwarding refs).

React.lazy

React.lazy() cho phép bạn định nghĩa một “thành phần” (component) được “tải” (load) một cách “linh động” (dynamically). Nó giúp giảm kích thước bundle để trì hoãn việc tải các “thành phần” (components) mà nó không sử dụng trong thời điểm “biểu diễn” (render) ban đầu.

Bạn có thể tìm hiểu cách sử dụng nó từ tài liệu chia nhỏ mã (code splitting documentation) của chúng tôi. Bạn có thể cũng muốn xem bài viết này giải thích làm thế nào để sử dụng nó chi tiết hơn.

// This component is loaded dynamically
const SomeComponent = React.lazy(() => import('./SomeComponent'));

Lưu ý việc “biểu diễn” (rendering) các “thành phần” (components) lazy đòi hỏi phải có một “thành phần” (component) <React.Suspense> cao hơn trong “cây biểu diễn” (rendering tree). Đây là cách bạn chỉ định một “chỉ thị tải” (loading indicator).

Lưu ý

Sử dụng React.lazy với “nạp động” (dynamic import) đòi hỏi phải có Promises trong môi trường JS. Điều này đỏi hỏi một polyfill trên IE11 hoặc thấp hơn.

React.Suspense

<<<<<<< HEAD React.Suspense cho phép bạn chỉ định “chỉ thị tải” trong trường hợp một số “thành phần” (component) trong cây bên dưới chưa sẵn sàng để “biểu diễn” (render). Hiện tại, các “thành phần” (component) lazy loading là trường hợp sử dụng duy nhất được hỗ trợ bởi <React.Suspense>: ======= React.Suspense lets you specify the loading indicator in case some components in the tree below it are not yet ready to render. Today, lazy loading components is the only use case supported by <React.Suspense>:

81124465ac68335b2e3fdf21952a51265de6877f

// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // Displays <Spinner> until OtherComponent loads
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

Nó được ghi lại trong hướng dẫn tách mã của chúng tôi. Lưu ý các “thành phần” (component)lazy có thể nằm sâu bên trong cây Suspense — nó không cần phải bọc từng cái một. Thói quen tốt nhất là đặt <Suspense> nơi bạn muốn xem một sự kiện báo “tải” (loading), nhưng không dùng lazy() ở bất cứ nơi nào bạn muốn chia nhỏ mã.

Mặc dù điều này chưa được hỗ trợ hiện nay, nhưng trong tương lai chúng tôi có kế hoạch để cho Suspense xử lý nhiều kịch bản hơn như “nạp dữ liệu” (data fetching). Bạn có thể đọc về điều này trong lộ trình của chúng tôi.

Lưu ý:

React.lazy()<React.Suspense> chưa được ReactDOMServer hỗ trợ. Đây là một điểm hạn chế sẽ được giải quyết trong tương lai.