- vừa được xem lúc

React Context API

0 0 65

Người đăng: Nguyen Thanh Hai

Theo Viblo Asia

Bạn đã bao giờ phải truyền một prop xuống 1 component trong React chỉ với mục đích truyền tiếp nó xuống component con của nó chưa? Đó chính xác là vấn đề mà React Context API cố gắng để cải thiện.

Vấn đề

Hãy cùng xem ví dụ sau:

  • Chúng ta có một loại dữ liệu là 1 số với giá trị là 10.
  • Chúng ta cần dữ liệu này trong component Red và Green.
  • Component Green là con của component Blue, và Blue lại là con của component Red.
  • Vì vậy chúng ta sẽ cần phải gửi dữ liệu từ Red đến Blue chỉ để gửi nó tới Green.

Với hình trên thì code của chúng ta sẽ tương tự như sau:

const Green = (props) => ( <div className="green">{props.number}</div>
)
const Blue = (props) => ( <div className="blue"> <Green number={props.number} /> </div>
) class Red extends Component { state = { number : 10 } render() { return <div className="red"> {this.state.number} <Blue number={this.state.number} /> </div> }
}

Chúng ta đã gửi data xuống cho component Blue chỉ để truyền tiếp nó xuống cho Green. Đây mới chỉ là ví dụ đơn giản thôi. Thử tưởng tượng mọi chuyện sẽ tồi tệ thế nào nếu chúng ta có 10 tầng component lồng nhau.

Cho đến React 16.3 thì giải pháp cho vấn đề này là sử dụng Redux hoặc Mobx hoặc bất cứ thư viện nào để xử lý state. Nhưng giờ thì chúng ta đã có giải pháp nằm trong React luôn.

Giải pháp: Quản lý state bằng React Context?

React Context cung cấp cho chúng ta cơ chế định nghĩa các data store và truy xuất chúng khi cần. Chúng ta không cần phải truyền data thông qua props nữa. Với React Context chúng ta có thể định nghĩa và sử dụng một thứ giống như là "global state" của ứng dụng vậy.

Cách dùng React Context?

Có 2 bước để setup React context trong ứng dụng của chúng ta:

  1. Setup một Context Provider và định nghĩa các dữ liệu bạn cần chứa trong đó.

  2. Sử dụng một Context Consumer bất cứ khi nào bạn cần sử dụng dữ liệu trong store.

Chúng ta có thể khởi tạo một Context Provider thông qua việc sử dụng hàm React.createContext. Chúng ta sẽ tạm gọi context này là AppContext:

const AppContext = React.createContext()

AppContext sẽ được sử dụng để tạo ra một context provider component. Provider này sẽ chứa dữ liệu chúng ta cần trong state của nó và nó sẽ gói toàn bộ nội dung của component Red:

class AppProvider extends Component { state = { number : 10, }
render() { return <AppContext.Provider value={this.state}> </AppContext.Provider> }
} //... class Red extends Component { render() { return <AppProvider> <div className="red"> <Blue /> </div> </AppProvider> }
}

Tóm tắt lại thì bằng việc gói mọi thứ vào bên trong AppProvider, chúng ta có thể dễ dàng inject dữ liệu từ attribute value khi cần. Bởi vì AppProvider được sử dụng như là 1 wrapper component, chúng ta sẽ phải dùng {this.props.children} trong hàm render.

Sau khi đã setup xong provider, chúng ta có thể truy xuất data bằng cách sử dụng Context Consumer.

<AppContext.Consumer> {(context) => context.number}
</AppContext.Consumer>

Mọi dữ liệu chúng ta thêm vào trong property value của AppContext.Provider sẽ có thể truy xuất thông qua tham số context của arrow function.

Code của chúng ta sẽ như dưới đây:

const AppContext = React.createContext()
class AppProvider extends Component { state = { number : 10 }
render() { return <AppContext.Provider value={this.state}> {this.props.children} </AppContext.Provider> }
}
const Green = () => ( <div className="green"> <AppContext.Consumer> {(context) => context.number} </AppContext.Consumer> </div>
)
const Blue = () => ( <div className="blue"> <Green /> </div>
) class Red extends Component { render() { return <AppProvider> <div className="red"> <AppContext.Consumer> {(context) => context.number} </AppContext.Consumer> <Blue /> </div> </AppProvider> }
}

Hãy chú ý rằng chúng ta không còn cần phải truyền prop number xuống component Blue hay Green nữa. Tất cả dữ liệu đã được xử lý bởi cơ chế của React Context.

Sử dụng actions và thay đổi data với React Context

Trừ khi bạn đang làm một cái app tí hon ra thì chắc chắn bạn sẽ cần một cách nào đó để cập nhật/thay đổi data từ React Context. Một ví dụ đơn giản cho tình huống này là chúng ta sẽ có một button với chức năng tăng giá trị của number.

Chúng ta sẽ cần một cách nào đó thay cho action của Mobx hoặc Redux.

Cái này thực ra khá là dễ. Điều chúng ta cần làm là định nghĩa một hàm trong state của AppProvider, và xử lý các thay đổi tới dữ liệu trong state.

class AppProvider extends Component { state = { number : 10, inc: () => { this.setState({number: this.state.number + 1}) } } //...
}

Sau khi định nghĩa xong hàm, chúng ta có thể sử dụng nó thông qua AppContext.Consumer và gọi nó trong event onClick:

const Blue = () => ( <div className="blue"> <AppContext.Consumer> {(context) => <button onClick={context.inc}>INC</button>} </AppContext.Consumer> <Green /> </div>
)

Đoạn code của chúng ta cuối cùng sẽ như thế này:

import React, { Component } from 'react'
const AppContext = React.createContext()
class AppProvider extends Component { state = { number : 10, inc: () => { this.setState({number: this.state.number + 1}) } } render() { return <AppContext.Provider value={this.state}> {this.props.children} </AppContext.Provider> }
}
const Green = () => ( <div className="green"> <AppContext.Consumer> {(context) => context.number} </AppContext.Consumer> </div>
)
const Blue = () => ( <div className="blue"> <AppContext.Consumer> {(context) => <button onClick={context.inc}>INC</button>} </AppContext.Consumer> <Green /> </div>
)

Dù đây là một api mới nhưng nó cũng có thể được coi là một trong những lựa chọn thay cho các giải pháp quản lý dữ liệu khác, nếu như mục đích của bạn chỉ là tránh việc phải truyền props một cách không cần thiết.

Bài viết được dịch từ How to use the new React context API của tác giả Daniel.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 501

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 376

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 701

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 335

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 421

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414