React v16.0 có gì mới

Như các bạn đã biết, từ hồi năm ngoái người ta đã rục rịch về việc React được viết lại core với cái tên React Fiber. Sau 1 năm hóng dài cổ, thì vào hôm 26/09/2017 vừa rồi Facebook đã release React v16.0 và dân tình đã chính thức được chạm tay vào version đầu tiên được build dựa trên Fiber. Trong bài viết này chúng sẽ cùng điểm qua vài tính năng mới nổi bật mà React v16.0 mang lại.

Cho phép render : fragmentsstrings

Trước đây một react element được return trong hàm render phải được bao lại bời 1 element như thế này

render() {
  return (
      <div>
          <li key="A">First item</li>
          <li key="B">Second item</li>
          <li key="C">Third item</li>
      </div>
  );
}

Điều này đôi khi gây ra một chút khó chịu khi cứ phải add thêm các element dư thừa. Và điều này đã được giải quyết trong phiên bản mới, chúng ta có thể làm như thế này

render() {
  // No need to wrap list items in an extra element!
  return [
    // Don't forget the keys :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

và chúng ta còn có thể return cả string nữa

render() {
  return 'Look ma, no spans!';
}

Trong tương lai, có thể React sẽ thêm vào một cú pháp dành cho kiểu fragments mà không yêu cầu chúng ta phải add key nữa.

Xử lý lỗi tốt hơn

Trước đây, runtime errors trong quá trình render sẽ khiến cho ứng dụng React rơi vào trạng thái lỗi, tạo ra các thông báo lỗi khó hiểu và yêu cầu phải làm mới trang để phục hồi. Để giải quyết vấn đề này React 16 sử dụng một chiến lược xử lý lỗi thông minh hơn. Theo mặc định, nếu một lỗi được throw bên trong các phương thức render hoặc lifecycle của component, toàn bộ cây component sẽ bị unmount từ root. Điều này ngăn chặn việc hiển thị dữ liệu bị lỗi. Tuy nhiên, đó có lẽ không phải là trải nghiệm người dùng lý tưởng.

Thay vì umount toàn bộ ứng dụng mỗi khi có lỗi, bạn có thể sử dụng error boundaries. Error boundaries là các thành phần đặc biệt bắt lỗi bên trong cây con của chúng và hiển thị giao diện dự phòng ở vị trí của nó. Hãy nghĩ error boundaries như câu lệnh try-catch, nhưng là cho các React Component.

Vậy chính xác thì cái error boundaries kia nó là cái gì ? Đơn giản mà nói React 16 cung cấp cho chúng ta 1 lifecycle method mới tên là componentDidCatch(error, info). Nếu một component định nghĩa lifecycle này nó sẽ trở thành 1 error boundary:

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

  componentDidCatch(error, info) {
    // Display fallback UI
    this.setState({ hasError: true });
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

Và chúng ta có thể sử dụng error boundary này như những component bình thường khác:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

Các bạn có thể đọc kĩ hơn ở đây

Portals

Portal cung cấp một cách đầu tiên để render các child element vào một DOM node tồn tại bên ngoài hệ thống phân cấp DOM của parent component với cú pháp ReactDOM.createPortal(this.props.children, domNode). Nghe có vẻ hơi khí hiểu 1 tý, chúng ta sẽ xem ví dụ sau. Giả sử chúng ta có view:

Trong ví dụ trên button Click sau khi được render không hề nằm trong thẻ div với event onClick, mà nằm trong thẻ <div id="modal-root"></div>. Thế nhưng khi click vào button nó vẫn thực thi event onClick.

Các bạn có thể đọc kĩ hơn ở đâydemo

Server-side rendering tốt hơn

React 16 bao gồm một server renderer đã viết lại hoàn toàn:

  • Hỗ trợ streaming
  • Chiến lược đóng gói mới, giúp chúng ta không còn phải bundle React để có được performance tốt.
  • Không còn yêu cầu initial render để kết hợp chính xác kết quả từ máy chủ. Thay vào đó, nó sẽ cố gắng sử dụng lại càng nhiều DOM hiện tại càng tốt

Để hiểu rõ hơn những thay đổi của SSR trong React 16 các bạn có thể tham khảo thêm bài viết của Sasha Aickin một thành viên của core team.

Hỗ trợ custom DOM attributes

Trước đây, React bỏ qua các thuộc tính DOM không xác định. Nếu chúng ta viết JSX với một thuộc tính mà React không nhận biết được, React sẽ bỏ qua nó. Ví dụ:

// Your code:
<div mycustomattribute="something" />

và sẽ hiển thị 1 div rỗng cho DOM với React 15

// React 15 output:
<div />

Trong React 16 điều này đã thay đổi, thay vì bỏ qua các thuộc tính đó thì giờ đây React sẽ tiếp tục truyền chúng cho DOM.

// React 16 output:
<div mycustomattribute="something" />

Điều này cho phép loại bỏ hầu hết các attribute whitelist của React, dẫn đến giảm kích thước tệp. Các bạn có thể đọc thêm tại đây

New core architecture

Và phần quan trọng nhất, chính là kiến trúc core mới. React 16 là phiên bản đầu tiên của React được xây dựng trên một kiến trúc lõi mới, codename "Fiber".

Fiber chịu trách nhiệm cho hầu hết các tính năng mới trong React 16, như error boundaries và fragments. Trong vài phiên bản tiếp theo, chúng ta có thể mong đợi nhiều tính năng mới hơn khi toàn bộ các tiềm năng của React được mở ra.

Có lẽ phần thú vị nhất là async rendering - một chiến lược lập kế hoạch công việc rendering bằng cách thực hiện theo trình tự định kỳ cho trình duyệt. Kết quả là, với việc hiển thị async, các ứng dụng có phản ứng nhanh hơn bởi vì React tránh blocking main thread.

Bản demo này cung cấp một cái nhìn đầu tiên về các loại vấn đề rendering async có thể giải quyết Async rendering là một vấn đề lớn, và đại diện cho tương lai của React. Để phiên bản v16.0 trơn tru nhất có thể, vẫn chưa có bất kì tính năng async nào trong phiên bản này cả, nhưng chúng sẽ bắt đầu được triển khai trong những tháng tới.