Rate this post

Dữ liệu trong ứng dụng React thường được chuyển đến các component thông qua prop. Khi sử dụng prop, dữ liệu được truyền từ component cha đến component con. Tuy nhiên, để tránh việc truyền prop qua từng tầng component, chúng ta có khả năng truyền dữ liệu trong toàn bộ ứng dụng mà không cần sử dụng prop qua mỗi component, thông qua chức năng của React Context.

Trong ứng dụng React, chúng tôi đã chuyển dữ liệu theo cách tiếp cận từ trên xuống thông qua các props. Đôi khi thật bất tiện đối với một số loại props được yêu cầu bởi nhiều component trong ứng dụng React. Context cung cấp một cách để chuyển các giá trị giữa các component mà không cần chuyển một cách rõ ràng một giá trị qua mọi cấp của cây component.

Vấn đề về context React

Nếu thiếu React Context, chúng ta phải sử dụng kỹ thuật “prop drilling,” trong đó chúng ta buộc phải truyền dữ liệu xuống các component, ngay cả khi một số component không cần sử dụng dữ liệu đó.

Ví dụ:

Giả sử có một dữ liệu, ví dụ như một số với giá trị là 10, và chúng ta muốn sử dụng dữ liệu này trong các component Red và Green.

Khi sử dụng “prop drilling,” chúng ta sẽ phải gửi dữ liệu từ component Red đến Blue, sau đó mới có thể chuyển dữ liệu đó xuống Green.

Điều này có nghĩa là chúng ta cần gửi dữ liệu đến component Blue chỉ để truyền nó xuống cho Green.

Quá trình truyền dữ liệu qua các component con sâu bên trong trở nên rối bời và không hiệu quả khi sử dụng “prop drilling.”

Vì vậy, React Context ra đời để khắc phục nhược điểm của “prop drilling.”

React Context cho phép chúng ta tạo dữ liệu và truyền nó thông qua một provider đến tất cả các component trong ứng dụng React mà không cần phải sử dụng “prop drilling.”

Sử dụng React Context

Chúng ta sẽ khám phá cách sử dụng React Context thông qua một ví dụ đơn giản.

Trong ví dụ này, chúng ta sẽ tạo một ngữ cảnh Food chứa name và location, sau đó truyền nó đến hai component khác nhau và cập nhật giá trị từ một component khác.

  1. Khởi tạo dự án React JS

Chạy: npx create-react-app learn-useContext

Cấu trúc thư mục như sau:

  1. Tạo Food Context

Trong FoodContext.jsx, khởi tạo một đối tượng Context bằng cách sử dụng API createContext.

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

const FoodContext = createContext();

export const FoodProvider = ({ children }) => {
  const [name, setName] = useState('Trà Xanh');
  const [location, setLocation] = useState('Thái Nguyên');

  return (
    <FoodContext.Provider value={{ name, location, setName, setLocation }}>
      {children}
    </FoodContext.Provider>
  )
}

export default FoodContext;

Ở đây, chúng ta tạo một hàm cung cấp để cung cấp ngữ cảnh vừa khởi tạo. Hàm này sẽ là cha của tất cả các component khác trong ứng dụng này. Dữ liệu trong giá trị như name, location, setName,… có thể truy cập từ tất cả các component con.

Cuối cùng, xuất FoodContext để tất cả các component con của FoodProvider có thể sử dụng.

  1. Bọc component App với Context

Ngữ cảnh là biến toàn cục.

Để dữ liệu ngữ cảnh có sẵn trong toàn bộ ứng dụng, trong index.js, chúng ta import FoodProvider và bọc .

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { FoodProvider } from './FoodContext';

ReactDOM.render(
  <FoodProvider>
    <App />
  </FoodProvider>,
  document.getElementById('root')
);
  1. Sử dụng name và location trong các component

Trong NameComponent.jsx, import FoodContext và sử dụng hook useContext.

import React, { useContext } from 'react';
import FoodContext from '../FoodContext';

const NameComponent = () => {
  const food = useContext(FoodContext);

  return (
    <div style={{ marginTop: "30px" }}>
      <h2 className="is-size-4">
        <strong>Name</strong>: {food.name}
      </h2>
    </div>
  )
}

Tương tự với LocationComponent.jsx

  1. Cách cập nhật dữ liệu trong ngữ cảnh

Tương tự, trong FoodForm.jsx, import FoodContext và sử dụng hook useContext để lấy dữ liệu ngữ cảnh.

import React, { useContext } from 'react';
import FoodContext from './FoodContext';

const FoodForm = () => {
  const food = useContext(FoodContext);

  return (
    <div className="food-form">
      <div className="input-item">
        <label className="label" style={{ marginRight: "28px" }}>Update Name: </label>
        <input
          className="input"
          onChange={e => food.setName(e.target.value)}
        />
      </div>

      <div className="input-item">
        <label className="label" >Update Location: </label>
        <input
          className="input"
          onChange={e => food.setLocation(e.target.value)}
        />
      </div>
    </div>
  )
}

export default FoodForm;
  1. Thêm style

Trong index.css:

/* ... */

Khi nào sử dụng Context

Context được sử dụng để chia sẻ dữ liệu có thể được coi là “toàn cầu” cho cây component React và sử dụng dữ liệu đó khi cần thiết, chẳng hạn như người dùng được xác thực hiện tại, chủ đề, v.v. Ví dụ: trong đoạn mã dưới đây, chúng tôi phân luồng theo cách thủ công qua một ” chủ đề “hỗ trợ tạo kiểu cho component Node.

class App extends React.Component {  
  render() {  
    return <Toolbar theme="dark" />;  
  }  
}  
  
function Toolbar(props) {  
  return (  
    <div>  
      <ThemedButton theme={props.theme} />  
    </div>  
  );  
}  
  
class ThemedButton extends React.Component {  
  render() {  
    return <Button theme={this.props.theme} />;  
  }  
}  

Trong đoạn mã trên, component chức năng của Thanh công cụ có thêm một “chủ đề” và chuyển nó đến ThemedButton. Nó có thể trở nên bất tiện nếu mọi nút trong ứng dụng cần biết chủ đề vì nó sẽ được yêu cầu chuyển qua tất cả các component. Nhưng sử dụng context, chúng ta có thể tránh chuyển props cho mọi component thông qua các component trung gian.

Chúng ta có thể hiểu nó từ ví dụ dưới đây. Ở đây, context chuyển một giá trị vào cây component mà không phân luồng rõ ràng nó qua mọi component.

// Create a context for the current theme which is "light" as the default.  
const ThemeContext = React.createContext('light');  
  
class App extends React.Component {  
  render() {  
    /* Use a ContextProvider to pass the current theme, which allows every component to read it, no matter how deep it is. Here, we are passing the "dark" theme as the current value.*/  
  
    return (  
      <ThemeContext.Provider value="dark">  
        <Toolbar />  
      </ThemeContext.Provider>  
    );  
  }  
}  
  
// Now, it is not required to pass the theme down explicitly for every component.  
function Toolbar(props) {  
  return (  
    <div>  
      <ThemedButton />  
    </div>  
  );  
}  
  
class ThemedButton extends React.Component {  
  static contextType = ThemeContext;  
  render() {  
    return <Button theme={this.context} />;  
  }  
}  

React API context

React Context API là một cấu trúc component, cho phép chúng tôi chia sẻ dữ liệu trên tất cả các cấp của ứng dụng. Mục đích chính của Context API là giải quyết vấn đề khoan chân đế (còn được gọi là “Threading”). API context trong React được đưa ra bên dưới.

  • React.createContext
  • Context.provider
  • Context.Consumer
  • Class.contextType

React.createContext

Nó tạo ra một đối tượng context. Khi React hiển thị một component đăng ký đối tượng context này, thì nó sẽ đọc giá trị context hiện tại từ trình cung cấp phù hợp trong cây component.

Cú pháp

const MyContext = React.createContext (defaultValue);

Khi một component không có Nhà cung cấp phù hợp trong cây component, nó sẽ trả về đối số defaultValue. Nó rất hữu ích cho việc thử nghiệm cách ly các component (riêng biệt) mà không cần bọc chúng.

Context.Provider

Mọi đối tượng Context đều có component Provider React cho phép các component tiêu thụ đăng ký các thay đổi context. Nó hoạt động như một dịch vụ giao hàng. Khi một component người tiêu dùng yêu cầu một cái gì đó, nó sẽ tìm thấy nó trong context và cung cấp nó đến nơi cần thiết.

Cú pháp

<MyContext.Provider value={/* some value */}>  

Nó chấp nhận giá trị chống đỡ và chuyển đến các component tiêu thụ là con cháu của Nhà cung cấp này. Chúng tôi có thể kết nối một Nhà cung cấp với nhiều người tiêu dùng. Trình cung cấp context có thể được lồng vào nhau để ghi đè các giá trị sâu hơn trong cây component. Tất cả người tiêu dùng là con cháu của Nhà cung cấp luôn hiển thị lại bất cứ khi nào hỗ trợ giá trị của Nhà cung cấp được thay đổi. Các thay đổi được xác định bằng cách so sánh các giá trị cũ và mới bằng cách sử dụng cùng một thuật toán như thuật toán Object.is.

Context.Consumer

Nó là component React đăng ký các thay đổi context. Nó cho phép chúng tôi đăng ký vào context trong component chức năng. Nó yêu cầu chức năng như một component. Người tiêu dùng được sử dụng để yêu cầu dữ liệu thông qua nhà cung cấp và thao tác với kho lưu trữ dữ liệu trung tâm khi nhà cung cấp cho phép.

Cú pháp

<MyContext.Consumer>  
       {value => /* render something which is based on the context value */}  
</MyContext.Consumer>  

component chức năng nhận giá trị context hiện tại và sau đó trả về một nút React. Đối số giá trị được truyền cho hàm sẽ bằng với giá trị hỗ trợ cho context này trong cây component. Nếu không có Provider  cho context này, đối số giá trị sẽ bằng với defaultValue đã được chuyển đến createContext ().

Class.contextType

Thuộc tính contextType trên một lớp được sử dụng để gán một đối tượng Context được tạo bởi React.createContext (). Nó cho phép bạn sử dụng giá trị hiện tại gần nhất của loại context đó bằng cách sử dụng this.context. Chúng ta có thể tham chiếu điều này trong bất kỳ phương thức vòng đời component nào, bao gồm cả hàm kết xuất.

Lưu ý: Chúng tôi chỉ có thể đăng ký một context duy nhất bằng cách sử dụng API này. Nếu chúng ta muốn sử dụng cú pháp của trường lớp công khai thử nghiệm, chúng ta có thể sử dụng trường lớp tĩnh để khởi tạo contextType.

Ví dụ về API context của React

Bước1 Tạo một ứng dụng React mới bằng lệnh sau.

$ npx create-react-app mycontextapi

Bước 2 Cài đặt khung CSS bootstrap bằng lệnh sau.

$ npm install react-bootstrap bootstrap --save    

Bước 3 Thêm đoạn mã sau vào tệp src / APP.js.

import React, { Component } from 'react';  
import 'bootstrap/dist/css/bootstrap.min.css';  
  
const BtnColorContext = React.createContext('btn btn-darkyellow');  
  
class App extends Component {  
  render() {  
    return (  
      <BtnColorContext.Provider value="btn btn-info">  
        <Button />  
      </BtnColorContext.Provider>  
    );  
  }  
}  
  
function Button(props) {  
  return (  
  <div className="container">  
    <ThemedButton />      
  </div>  
  );  
}  
  
class ThemedButton extends Component {  
    
  static contextType = BtnColorContext;  
  render() {  
    return <button className={this.context} >  
      welcome to React  
    </button>;  
  }  
}  
export default App;  

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Contact Me on Zalo
Call now