React “Aha” Moments
Bài đăng này đã không được cập nhật trong 3 năm
Introduction
Khi tiếp xúc với một ngôn ngữ, thư viện những khái niệm chúng đặt ra có thể khiến chúng ta phải quay vòng vòng một thời gian. Rồi đến một thời điểm nào đó, chúng ta bỗng đọc được một từ nào đấy, một câu nào đấy và "À ra thế". Bài dịch dưới tổng hợp lại những khoảnh khắc chúng ta nhận ra React không quá phức tạp như ta vẫn tưởng tượng. Hi vọng phần nào giúp những người mới tiếp xúc dễ hình dung hơn về những khái niệm của React.
Let's Start
Moment 1: props
với components
giống như arguments
với functions
.
Một trong những phần tốt nhất của React là ta có thể có cảm giác giống với Javascript functions, và sử dụng nó để xác định xem khi nào nên tạo một React component
. Nhưng với React, thay vì nhận arguments
và trả về value
thì chúng ta sẽ nhận arguments
và trả về một object đại diện cho UI
.
Có thể tóm gọn lại như sau "Một function nhận dữ liệu và trả ra view" : fn(d) = V
Đây là một hướng tốt để nghĩ về lập trình UI, bời vì giờ đây UI của ta chỉ là bao gồm những lời gọi function khác nhau. Và có thể các bạn không để ý components có thể là class hoặc function
Moment 2: Trong React, UI của toàn bộ ứng được xây dựng bởi tập hợp các functions. JSX
là một lớp trừu tượng (abstraction
) bên trên những functions này.
Phản ứng thông thường nhất từ những người lần đầu sử dụng React kiểu "React nhìn hay đấy, nhưng tôi ko thích JSX. Nó phá vỡ nguyên lý separation of concerns".
JSX không cố trở thành HTML, và nó chắc chắn không chỉ là một templating language. Có 2 điều quan trọng để hiểu về JSX.
Thứ nhất, JSX
là một trừu tượng (abstraction
) trên React.createElement
, là một function trả về một object đại diện cho DOM
. Chúng ta viết JSX, nó sẽ được biên dịch lại và chúng có một JavaScript object
đại diện cho DOM thực - bất kể nền tảng (iOS, Android, ect). Sau đó React có thể phân tích object đó và DOM thực, và update DOM xảy ra sự thay đổi. Điều này có một số mặt tích cực, nhưng quan trọng nhất, nó cho thấy JSX thực sự "chỉ là JavaScript".
Thứ hai, vì JSX chỉ là JavaScript, ta nhận được tất cả những lợi ích mà JavaScript cung cấp - chẳng hạn như composition, linting, and debugging. Nhưng ta vẫn có thể có những khai báo đơn giản (và quen thuộc) của HTML.
Moment 3: Components
không nhất thiết phải trả về DOM nodes
.
Bắt đầu học React, ta được dạy răng "Components xây dựng các khối của React. Chúng nhận input và trả về UI".
Liệu điều đó có nghĩa rằng tất cả các components
cần phải trực tiếp trả về các UI descriptor như ta được dạy ? Sẽ thế nào nếu ta muốn component render một component khác (Higher Order Component pattern). Sẽ thế nào nếu ta muốn một component quản lý một số phần state và thay vì trả về một UI descriptor, nó sẽ trả về một lời gọi function truyền đi trong state (Render Props pattern).
Một điều tuyệt vời về React là chúng ta không phải
trả về "views" từ components. Miễn là những gì cuối cùng được trả là một React element, null
hoặc false
.
Ta có thể trả về component khác:
render () {
return <MyOtherComponent />
}
Ta có thể trả về lời gọi function:
render () {
return this.props.children(this.someImportantState)
}
Hay cũng có thể trả về null:
render () {
return null
}
Momnent 4: Khi 2 component
cần chia sẻ state
, việc cần làm không phải
là cố gắng đồng bộ (sync) state
của chúng với nhau.
Một kiến trúc Component-based làm cho việc chia sẻ state trở nên khó khăn. Nếu 2 components dựa trên cùng state thì state đó sẽ tồn tại ở đâu ?
Đây là một câu hỏi phổ biến, đã thúc đẩy hệ sinh thái giải pháp (ecosystem of solutions), mà cuối cùng đã kết thúc với Redux.
Cách giải quyết của Redux là đặt shared state vào một vị trí khác gọi là store
. Component có thể đăng ký (subscribe) với bất kì phần nào của store
mà chúng cần, và cũng có thể gửi (dispatch) actions
để update store
.
Cách giải quyết của React là tìm một parent gần nhất của những component này và parent đó sẽ quản lý state, gửi state xuống cho component con cần.
Với mỗi phương pháp tiếp cận, đều có những ưu và nhược điểm riêng, nhưng điều quan trọng, là chúng ta cần biết được sự tồn tại của cả 2 phương pháp.
Moment 5: Kế thừa (Inheritance)
không cần thiết trong React. Containment và Specialization đều có thể đạt được với các thành phần (composition).
React luôn rất tự do trong việc áp dụng các nguyên lý của functional programming. React đã chuyển từ kế thừa (Inheritance) sang thành phần (composition) từ phiên bản 0.13, điều này được làm rõ với việc React không còn hỗ trợ Mixins với ES6 classes.
Lý do điều là hầu hết tất cả những gì chúng ta làm được với Mixins (hay inheritance) chúng ta đều có thể đạt được với composition - nhưng với ít side effects hơn.
Nếu bạn đến với React với tư tưởng nặng kế thừa, cách suy nghĩ này sẽ hơi khó khăn và không tự nhiên.
Moment 6: Sự phân tách container
và presentational components
Nếu chúng ta nghĩ tới việc phân tích React component, nó thường liên quan đến state, lifecycle hooks, và markup JSX.
Chuyện gì xảy ra nếu thay vì có tất cả những thứ trên trong một component, ta có thể tách state và lifecycle hooks
ra khỏi markup
. Điều có có thể cho ta 2 components. Component thứ 1 có state, life cycle methods
và chịu trách nhiệm về cách thức component hoạt động. Component thứ 2 nhận data từ props và chịu trách nhiệm component sẽ trông như thế nào.
Cách tiếp cận này cho phép tái sử dụng sự component trình bày (presentational components) một cách tốt hơn, khi chúng không bị gắn lại với dữ liệu mà chúng nhận được.
Điều này cũng cho phép ta ( và những người mới) hiểu rõ hơn về cấu trúc ứng dụng. Ta có thể thay đổi việc thực thi của component mà ko cần quan tâm đến UI và ngược lại. Kết quả là, designers có thể tinh chỉnh UI mà ko phải lo lắng về việc component phải nhận data như thế nào.
Có thể tìm hiểu kĩ hơn qua bài viết Presentational and Container Components
Moment 7: Cố găng giữ components pure và stateless việc maintain sẽ trở nên đơn giản hơn rất nhiều.
Đây là một lợi ích khác của việc phân tách presentational components và container components. State luôn đi kèm với sự mâu thuẫn. Bằng cách phân tách một cách đúng đẵn, ta có thể cải thiện đáng kể khả năng dự báo (predictability) của ứng dụng bằng cách đóng gói sự phức tạp lại.
Nguồn
React “Aha” Moments React Elements VS React Components Presentational and Container Components
All rights reserved