-->
ads here

Làm quen với React context trong 5 phút

advertise here
Trong bài viết hôm nay chúng ta sẽ cùng tìm hiểu cách sử dụng một tính năng của React là Context. React context cho phép chúng ta quản lý global state của ứng dụng React mà không cần dùng đến bên thứ 3 như Redux hay MobX và cũng không gặp phải vấn đề prop drilling
Nội dung bài viết gồm các mục sau:
  1. Prop drilling là gì?
  2. Giới thiệu React context.
  3. Các Context API
  4. Ví dụ
enter image description here

1. Prop drilling là gì?

Chắc hẳn mọi người làm việc với React đều đã quen thuộc với với cấu trúc phân cấp của React, component cha bao các component con.
enter image description here
Và Prop drilling chính là quá trình chúng ta truyền data từ component A đến Z thông qua các nhiều tầng component ở giữa. Component Z sẽ nhận được data một cách gián tiếp và nhiệm vụ của developer.
enter image description here
Vậy nên để giải quyết được vấn đề này, chúng ta có thể dùng một số thư viện quản state của React như redux hoặc MobX. Ngoài ra, chúng ta có thể sử dụng 1 built-in feature của React là Context, sẽ được giới thiệu tiếp theo đây.

2. Giới thiệu React Context

Về khái niệm, theo trang chủ của React,
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
Context cho phép ta truyền data vào các component mà không phải đi từng bước ở mỗi tầng trong component tree.
enter image description here
Nhờ có Context, ta có thể truyền data thông qua component tree thông qua bộ đôi Provider-Consumer mà không phải truyền prop qua từng tầng component.
Để hiểu rõ hơn, trong phần tiếp theo chúng ta sẽ tìm hiểu các API của React.Context

3. Các context API

React.createContext

const DemoContext = React.create Context(defaultValue)
createContext tạo ra một Context Object. Khi React render 1 component mà subscibe vào Context Object này, nó sẽ đọc được context value của Provider gần nó nhất trên component tree.

Context.Provider

<DemoContext.Provider value={/* some value*/}> <App /> </Demo.Provider>
Mỗi Context Object đều đi kèm với một Provider React component, nhờ đó các consuming component có thể subscribe khi context thay đổi

Class.contextType

class MyClass extends React.Component { render() { return <App /> } } MyClass.contextType = DemoContext
contextType là một thuộc tính của class mà có thể được gán bởi Context Object mà đc tạo bởi React.createContext ở trên. Chúng ta có thể sử dụng giá trị của Context thông qua this.context và biến này có thể được gọi ở bất kì lifecycle method nào của React, kể cả render()

Context.Consumer

<DemoContext.Consumer> {value => /* render component*/ } </Demo.Consumer>
Context.Consumer là một React component sẽ subscribe những thay đổi của context. Context.Consumer nhận 1 function để render component con. Function này sẽ nhận giá trị của context và trả về một React node.

useContext

useContext là một React hooks mới được giới thiệu để sử dụng Context trong Functional Component
useContext sẽ nhận vào là một context được tạo ra từ React.createContext và trả về giá trị hiện tại của context đó
import React, {useContext} from 'react'; import DemoContext from './DemoContext'; const DemoComponent = (props) => { const contextValue = useContext(DemoContext); return ( <span>{contextValue}</span> ) }
Như vậy chúng ta đã điểm qua React.Context là gì và một số API của nó. Trong phần cuối của bài viết này mình sẽ hiện thực một ví dụ để nắm rõ cách sử dụng context trong thực tế.

4. Ví dụ

Chúng ta sẽ hiện thực một use case điển hình của việc sử dụng React.Context đó là tính năng bật tắt Dark Mode của một application.
Để bắt đầu, chúng ta sẽ định nghĩa một context và chứa giá trị mặc định là light theme như sau
// ThemeContext.js import React from 'react'; const themes = { light: { foreground: "#000000", background: "#eeeeee" }, dark: { foreground: "#ffffff", background: "#222222" } }; const ThemeContext = React.createContext({ theme: themes.light }); export default ThemeContext;
Tiếp theo chúng ta sẽ wrap ứng dụng của chúng ta trong Provider.
// App.js export default class App extends React.Component { return ( <ThemeContexr.Provider value={themes.light}> <Main /> </ThemeContext.Provider> ) }
Giả sử trong Main có 1 component là ThemedButton cần thay đổi UI khi theme thay đổi, ta sẽ thực hiện như sau
// ThemedButton.js class ThemedButton extends React.Component { render() { let theme = this.context.theme; return ( <button style={{backgroundColor: theme.background}}> This is themed button </button> ) } } ThemedButton.context = ThemeContext; export default ThemedButton;
Lúc này, mỗi khi theme thay đổi thì button sẽ thay đổi UI tương ứng theo mà không cần phải truyển props từ Main vào lần lượt đến ThemedButton.
Một cách khác chúng ta có thể sử dụng useContext hooks
// ThemedButton.js export default const ThemedButton = props => { const theme = useContext(ThemeContext); return ( <button style={{backgroundColor: theme.background}}> This is themed button </button> ) }
Hoặc chúng ta cũng có thểt dùng Context.Consumer
// ThemedButton.js export default const ThemedButton = props => { const theme = useContext(ThemeContext); return ( <ThemeContext.Consumer> { theme => ( <button style={{backgroundColor: theme.background}}> This is themed button </button> ) } </ThemeContext.Consumer> ) }

Một số lưu ý

  • Không cần dùng Context để tránh props drilling nếu ứng dụng của bạn chỉ có 1 đến 2 layer của component
  • Context không dùng để lưu local state của component. Thay vào đó hãy sử dụng this.state, chẳng hạn, bạn sẽ không cần dùng context để lưu thông từ <input />. Hãy dùng state.
  • Cuối cùng, khi bạn truyền 1 object vào giá trị của Context, hãy lưu ý đến vấn đề performance.

Kết

Qua bài viết này mình muốn giới thiệu và hướng dẫn các bạn sử dụng React.Context. Hi vọng nó sẽ có ích khi các bạn áp dụng React.Context vào quá trình làm việc của mình.
Nếu thấy hay, các bạn có thể share cho nhiều người cùng biết. Nếu có ý kiến đóng góp, đừng ngần ngại để lại comment bên dưới để các bài viết sau tốt hơn nhé. Thanks

Reference

Advertisement
COMMENTS ()