Sử dụng Context API trong React

4 min read

React Context

Thông thường trong React, bạn sẽ truyền data từ component cha xuống component con thông qua props. Nhưng việc chuyển data thông qua props có thể sẽ trở nên dài dòng và bất tiện nếu bạn phải chuyển chúng qua nhiều component (nhiều level component) hoặc nhiều component trong ứng dụng cần sử dụng cùng 1 thông tin (vd: thông tin user đăng nhập, theme). Việc này có thể dẫn đến tình huống sẽ có nhiều component bị re-render lại 1 cách không cần thiết do giá trị của props bị thay đổi.

Chúng ta cùng đi vào phân tích 1 trường hợp cụ thể dưới đây

React Context API 1

Giả sử chúng ta đang có User Data đang được truyền từ component E xuống component G (là con của E). Tuy nhiên sau đó component J lại muốn sử dụng User Data thì chúng ta làm như nào?

React Context API 2

Để giải quyết yêu cầu ở trên theo cách thông thường(truyền data thông qua props) thì chúng ta phải chuyển User Data lên thành state của Root Component sau đó truyền xuống các component con thông qua props(như hình bên dưới).

React Context API 3

Tuy nhiên, việc chuyển state lên component Root sẽ dẫn đến vấn đề gọi là “prop drilling“. Nếu sử dụng phương án trên chúng ta sẽ thấy vấn đề mỗi khi User Data thay đổi thì các component A, C, H cũng sẽ bị re-render lại trong khi các component này lại không sử dụng User Data. Để giải quyết vấn đề này, React giới thiệu khái niệm Flux (Flux concept) và Context API.

Context cho phép một component cha cung cấp data cho toàn bộ cây bên dưới nó (tree components) mà không cần phải truyền data thông qua props. Điều này giúp cho việc chia sẻ data giữa các component trở nên dễ dàng hơn. Chúng ta có thể lưu trữ dữ liệu toàn cục (global data) vào trong Context và lấy ra dữ liệu ở các component cần dữ liệu đó.

React Context API 4

Để sử dụng dữ liệu được lưu trữ trong context, bạn cần cung cấp Context Provider trong parent component (trong ví dụ trên là Root component) và cần sử dụng Context Consumer ở các component con cần lấy ra dữ liệu từ context (trong ví dụ trên là component G, J).

React Context API 5

Bây giờ chúng ta đi vào implement code cụ thể cho ví dụ trên

Bước 1: Khởi tạo context

Đầu tiên chúng ta tạo 1 thư mục mới đặt tên là context, sau đó tạo 1 file mới trong thư mục context và đặt tên là AppContext với nội dung như sau:

//AppContext file

import { createContext } from "react";

export const AppContext = createContext(null);

Hàm createContext sẽ trả về 1 context object, các component có thể đọc giá trị của context bằng cách sử dụng hàm useContext và truyền vào tham số là context object (cụ thể trong ví dụ này là AppContext).

Chúng ta sẽ set giá trị mặc định khi khởi tạo context là null, và các bạn có thể set giá trị default khác tùy mong muốn của các bạn. Lưu ý giá trị default sẽ không bao giờ thay đổi.

Bước 2: Khai báo Context Provider và set giá trị cho Context Provider

Ở file App (root component), chúng ta cần import file AppContext đã được khai báo ở bước 1.

import ComponentA from "./components/ComponentA";
import ComponentH from "./components/ComponentH";
import "./styles.css";
import { AppContext } from "./context/AppContext";
import { useState } from "react";

export default function App() {
  const [currentUser, setCurrentUser] = useState({ name: "Hoang Huu" });

  return (
    <AppContext.Provider value={currentUser}>
      <div className="App">
        <div className="component">
          <div className="box">Root Component</div>
          <div className="flex">
            <ComponentA />
            <ComponentH />
          </div>
        </div>
      </div>
      <div style={{ marginTop: "20px" }}>
        <label>User name: </label>
        <input
          type="text"
          placeholder="Enter user name..."
          value={currentUser.name}
          onChange={(ev) => {
            setCurrentUser({ name: ev.target.value });
          }}
        />
      </div>
    </AppContext.Provider>
  );
}

Ở đoạn code trên mình đang truyền giá trị từ State currentUser vào cho context Provider để có thể lấy ra sử dụng trong các component cần thiết.

Bước 3: Đọc value từ context và sử dụng trong các component

Để đọc value từ context chúng ta sử dụng hook function useContext của React với tham số truyền vào component này là AppContext

import { useContext } from "react";
import { AppContext } from "../context/AppContext";

const ComponentG = () => {
  const contextData = useContext(AppContext);
  return (
    <div className="component">
      <div className="box">
        Component G
        {contextData ? (
          <div className="context-value-box">
            Context data:{contextData.name}
          </div>
        ) : null}
      </div>
    </div>
  );
};

export default ComponentG;

Và kết quả cuối cùng các bạn có thể xem tại đây

Ví dụ sử dụng ContextAPI

Các trường hợp nên sử dụng Context API

Context chủ yếu được sử dụng khi một số dữ liệu cần được truy cập bởi nhiều thành phần ở các cấp độ lồng nhau khác nhau. Dưới đây là 1 số trường hợp các bạn nên sử dụng Context API

  • Theming: bạn có thể sử dụng Context API để lưu trữ giá trị theme hiện tại của ứng dụng và có thể sử dụng nó ở tất cả các component mà bạn muốn.
  • User Authentication: bạn có thể sử dụng Context API để lưu trữ thông tin của user hiện tại đang login trên ứng dụng và kiểm tra quyền truy cập các trang dựa theo permission của user.
  • Multilingual: nếu trang web của bạn có hỗ trợ nhiều ngôn ngữ thì bạn cũng có thể sử dụng Context API để lưu trữ trạng thái được chọn của ngôn ngữ hiện tại.
  • Truy cập dữ liệu từ những nguồn ngoài (external resources): bạn cũng có thể sử dụng Context API để lưu trữ dữ liệu được truy xuất từ các nguồn bên ngoài như API, cơ sở dữ liệu và cấp cho tất cả các component nếu cần. Ví dụ: dữ liệu về danh sách các quốc gia, đầu số điện thoại,…
  • Sử dụng Context API cho các form phức tạp có nhiều step (Wizard form).

Nếu bạn có góp ý gì về bài viết, bạn có thể comment bên dưới.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *