Sử dụng context để giao tiếp giữa component cha - con trong ReactJs

Sử dụng context để giao tiếp giữa component cha - con trong ReactJs

Đây là loạt bài viết nâng cao, có sử dụng nhiều khái niệm, từ ngữ trong hệ sinh thái React: ReactJs, Flux/Redux, Relay, GraphQL, Meteor. Trong blog FullstackStation đều có các bài viết giới thiệu, bạn cần nắm qua trước khi theo loạt bài này nhé!

Nội dung chính

Phần 1: Bài toán

Nếu bạn chưa sử dụng Flux cho dự án của mình, và có một vài vấn đề khó khăn liên quan đến việc giao tiếp giữa các components có quan hệ cha – con: component con muốn cập nhật dữ liệu cho component cha hoặc ông nội, ông cố… hoặc truyền dữ liệu thông qua props từ components ông cố -> ông nội -> cha -> con …thì bạn có thể sử dụng context để khắc phục vấn đề trên.

Context là một khái niệm thuộc phần nâng cao và đang trong quá trình thử nghiệm của React Js. Mặc dù API được khuyến cáo là có thể thay đổi, tuy nhiên với những xử lý Form phức tạp (có nhiều component con lồng nhau) thì mình nhận thấy dùng context khá dễ dàng và tiện lợi hơn so với Flux.

Context: https://facebook.github.io/react/docs/context.html

Ở tài liệu trên của Facebook, đã nói đến khía cạnh truyền dữ liệu từ Cha -> Con không thông qua props, bài viết này, mình giới thiệu với các bạn cách cập nhật dữ liệu cho component ông cố từ component con

Nếu bạn đã có khái niệm hiểu Flux là gì rồi, thì có thể tưởng tượng thay vì Store nằm ở một đối tượng khác – một nơi nào đó thì context tương tự store nằm trong Component ông cố, và khi khởi tạo component con sẽ lấy được dữ liệu từ Component ông cố thông qua Props, và mọi Action từ component con sẽ cập nhật component cố nội.

Giao diện

Xét Form sau: Để đơn giản, mình chỉ vẽ 3 cấp (ông nội – cha – con), còn component level 4, 5 sử dụng modal, xử lý dữ liệu và trả về cho component level 3 không hiển thị ở đây.

Context in Reactjs

Cơ sở dữ liệu

Tương ứng dữ liệu trong MongoDB có thể như sau:

{
  "title": "Good places near your house",
  "description": "Hospital, Supermarket, Kindergarden, Stadium...",
  "places": [
      { 
          "location": {
              "type": "Point",
              "coordinates": [1234, 4567]
           },
           "imageId": "feYddeqw12jx",
           "recommends": [
              "Open 10:00 - 19:00", "Good services"
           ]
      },
      {...},
      ....
   ]
  
}

Sử dụng MongoDB với embedded document thường sẽ làm cho React có cấu trúc component như trên – khá phức tạp đúng không? Nếu bạn sử dụng chung nguyên bộ React – Relay – GraphQL thì vấn đề trên chắc sẽ giải quyết gọn hơn, hoặc Flux/Redux.

Tuy nhiên, mình đã áp dụng Context trong dự án thực tế để giải quyết vấn đề trên, với form khá phức tạp ở các components, nhất là trong component level 2:

  • Map (component level 3): sử dụng Component Modal level 4 để chọn location
  • Image (component level 3) sử dụng Component Modal level 4 để dùng Google Custom Search chọn hình ảnh
  • Recommends (component level 3): mỗi component đều có nút xoá

Tất cả các dữ liệu component đều lưu trong 1 state thuộc component level 1, các component con ứng với mỗi action sẽ cập nhật state này (setState), state thay đổi kích hoạt render lại toàn bộ component con (chỉ những phần thay đổi).

Sơ đồ trao đổi dữ liệu

(Làm biếng vẽ hình quá, xem thô tạm nha)

 

———–Database (API)

————–↑          ↓

(Autosave)  ↑          ↓   (Reactive)

————–↑          ↓

(State) Component Cha → Props→(Render) Component con →Action

↑                                                                                                                        ↓

↑                                                                                                                        ↓

←———————-Context——————————————–←

 

Mô hình sử dụng context này, không những giúp cho component con có tính tái sử dụng, mà còn giúp cho ta tạo ra một ánh xạ document của MongoDB, việc Save document này sau đó khá là dễ dàng. Component Root có nhiệm vụ giao tiếp với Database và truyền props xuống các component con, mỗi khi có action từ component, ta cập nhật state cho component ông và có thể kích hoạt autosave lưu vào database. Nếu trong ứng dụng realtime, 2-n người tương tác với nhau thì Database sẽ reactive dữ liệu xuống, trong ứng dụng thực tế, mình sử dụng React – Meteor đã có sẵn tính năng reactive từ database.

Phần 1 đến đây là kết thúc, phần 2 mình sẽ trình bày cách lập trình để sử dụng context xử lý component con cấp n cập nhật dữ liệu cho component root.

Read more