Higher Order Component (HOC) trong React, React Native

1. Khái niệm

HOC


Higher order component (HOC) là một hàm nhận đối số là 1 component và trả về 1 component mới.

Nói đơn giản thì HOC là 1 function nhận vào 1 component như 1 argument và trả về một phiên bản mở rộng của component đó


2. Sử dụng khi nào?

Chúng ta đã biết HOC là gì rồi vậy thì khi nào chúng ta nên sử dụng nó? Chúng ta sử dụng nó khi:

  • Muốn thêm hay thay đổi các prop của 1 component
  • Xử lý các ngoại lệ (keyboard, style,...) mà bản thân component không cần thiết phải xử lý trong chính nó
  • Tái sử dụng code, maintain


3. Một số hạn chế của HOC

Mặc dù sử dụng HOC sẽ mang lại nhiều lợi ích nhưng nếu sử dụng tràn lan, không đúng cách có thể gây ra một số vấn đề sau:

  • Dễ gây bối rối: Việc sử dụng HOC cho một component dễ dẫn đến không biết props này do HOC nào truyền vào
  • Trùng lặp tên props dẫn tới việc props bị ghi đè.


4. Một số ví dụ phổ biến dùng HOC

  • Hàm connect của react-redux: Đây có lẽ là một hàm rất quen thuộc với những ai đã sử dụng redux vào các ứng dụng react để quản lý state. Hàm này sẽ kết nối component với store, khi đó trong component có thể sử dụng các props được map với state trong store và các method được liệt kê.
  • Hàm withRouter của react-router: giúp cho component con có quyền sử dụng các thuộc tính history, location hay match, lấy router từ context để biến thành thành prop cho các component.


5. Example sử dụng HOC

Dưới đây là 1 component để load danh sách các bài viết vào 1 scrollview, trong thời gian đợi api trả về dữ liệu thì ta sẽ cho hiển thị một spinner loading.

// PostList.js

import React, { Component } from 'react'; import { ScrollView } from 'react-native'; import LoadingIndicator from './LoadingIndicator'; export default class PostList extends Component { constructor(props) { super(props) this.state = { isLoading: true, postList: [], } } componentDidMount() { api.getPostList().then(responseData => { this.setState({ postList: responseData, isLoading: false, }) }) } render() { const { isLoading } = this.state; return isLoading ? (<LoadingIndicator/>) : ( <ScrollView> // View rendering post list </ScrollView> ) } } 
Vấn đề đặt ra là nếu có nhiều screen cũng theo cơ chế trên (trước khi data được load thì hiển thị spinner) thì việc lặp đi lặp lại code là điều không tránh khỏi, khi muốn thay thế spinner thì phải thay ở nhiều screen. => khó để maintain.=> Ta sẽ sử dụng HOC để giải quyết vấn đề này// withSpinner.js

import React from 'react'; import { ScrollView } from 'react-native'; import LoadingIndicator from './LoadingIndicator'; const withSpinner = Comp => ({ isLoading, children, ...props }) => { return isLoading ? <LoadingIndicator /> : ( <Comp {...props}> {children} </Comp> ) }; export default withSpinner;
Ở đây chúng ta tạo ra 1 component HOC nhận một thuộc tính isLoading, nếu true thì hiển thị spinner, nếu false thì hiển thị children component.Sửa lại file PostList.js như sau:// PostList.js

import React, { Component } from 'react'; import { ScrollView } from 'react-native'; import withSpinner from './withSpinner'; const ScrollViewWithSpinner = withSpinner(ScrollView); export default class PostList extends Component { constructor(props) { super(props) this.state = { isLoading: true, postList: [], } } componentDidMount() { api.getPostList().then(responseData => { this.setState({ postList: responseData, isLoading: false, }) }) } render() { const { isLoading } = this.state; return ( <ScrollViewWithSpinner isLoading={isLoading}> // View rendering post list </ScrollViewWithSpinner> ) } }
Với việc tách riêng ra như vậy ta hoàn toàn có thể tái sử dụng lại HOC component cho nhiều screen

Thông qua các khái niệm và ví dụ trên, mong rằng các bạn có thể hiểu về HOC để có thể áp dụng vào các dự án thực tế của mình với React, React Native. Chúc các bạn thành công.

Từ khóa: vtcc_intern_7, react, react-native, Công nghệ thông tin

Xem thêm ví dụ và cách sử dụng tại đây

Trả lời

Xem thêm ví dụ và cách sử dụng tại đây