Trong thời đại công nghệ hóa hiện nay dưới sự phát triển vượt bậc của ngành công nghệ điện tử kéo theo những ngành nghề liên quan cũng phát triển trong đó có cả việc sử dụng những thư viện JavaScript cho các website. Vì thế React đã ra đời và trở nên phổ biến bởi tính năng linh hoạt đơn giản mà nó đem lại
Trong bài viết này, chúng ta sẽ tìm hiểu React là gì, một số khái niệm “nhập môn” của React và cùng nhau thực tập để làm 1 App ToDo List
1. React là gì?
React được hiểu nôm na là một thư viện trong đó có chứa nhiều JavaScript mã nguồn mở và cha đẻ của React đó chính là một ông lớn với cái tên ai cũng biết đó chính là Facebook. Mục đích của việc tạo ra React là để tạo ra những ứng dụng website hấp dẫn với tốc độ nhanh và hiệu quả cao với những mã hóa tối thiểu. Và mục đích chủ chốt của React đó chính là mỗi website khi đã sử dụng React thì phải chạy thật mượt thật nhanh và có khả năng mở rộng cao và đơn giản thực hiện.
2. Các khái niệm cơ bản
Hãy cùng tìm hiểu 1 số khái niệm cơ bản trong React.
2.1 Component:
Trong React chúng ta có 2 cách viết component. Đó là dùng Function và dùng Class.
Functional component:
- Là các hàm JavaScript căn bản. Đây thường là các arrow functions hoặc cũng có thể tạo ra bằng với từ khóa function.
- React lifecycle methods (ví dụ như componentDidMount) sẽ không thể sử dụng trong functional component.
- Không có render() method.
- Nhiệm vụ chính là nhận props để render UI và bắn event khi cần thiết cho Container components.
Một function component sẽ được viết như sau:
Class component:
- Là những components có state, có lifecycle hooks.
- Sử dụng các class của ES6 và mở rộng Component class trong React.
- React lifecycle methods có thể sử dụng bên trong Class Component.
- Như là một trung tâm xử lý dữ liệu của một tổ chức, Class Component thường được dùng để tạo nên những Container Components, chúng có nhiệm vụ nhận event, quản lí state, logic.
Một class component sẽ được viết như sau:
2.2 Constructor:
Trong bất kỳ các ngôn ngữ lập trình, constructor là 1 method sẽ được gọi tự động khi khởi tạo 1 đối tượng từ 1 class. Trong React cũng tương tự như vậy. Nó được dùng để bind các events đến các components và khởi tạo local state.
Constructor method sẽ được chạy trước khi component Mounted (phần này sẽ tìm hiểu rõ hơn tại Component lifecycle). Và sẽ có 1 số rules nhất định khi chúng ta sử dụng chúng.
- Gọi super(props) trước khi sử dụng this.props
Trong JavaScript, super để gọi lại constructor của class cha. (Trong ví dụ này, nó trỏ về React.Component.)
Điều quan trọng là không thể sử dụng this trong constructor nếu chưa gọi đến constructor của class cha. JavaScript sẽ không để ta làm việc này.
Hãy tham khảo 1 ví dụ sau để rõ hơn
Nếu như chúng ta sử dụng this trước super, rồi 1 năm sau ta thay đổi function getEmployeeName như sau:
Nhưng chúng ta quên rằng this.getEmployeeName() được gọi trước super(), giá trị this.name chỉ có sau khi gọi super()! Và đó chính là lý do!
- Không bao giờ được gọi hàm setState() trong constructor()
Constructor là nơi để khởi tạo nên local state, vì thế thay vì sử dụng setState() chúng ta sẽ sử dụng như sau:
constructor() là nơi duy nhất mà chúng ta nên gán local state như trên, còn lại bất cứ nơi nào khác chúng ta đều sẽ dử dụng setState().
- Tránh gán giá trị từ this.props cho this.state
Điều này là hoàn toàn dư thừa, thay vì chúng ta gán như vậy. Chúng ta có thể trực tiếp sử dụng giá trị từ this.props
Và trên đây là 1 số rules mà tôi tìm hiểu được trong React, hy vọng nó có thể giúp ích cho chúng ta.
2.3 Props:
Dữ liệu trong states và props được sử dụng để render ra các component. Đầu tiên chúng ta hãy cùng tìm hiểu xem props có chức năng gì và sử dụng như thế nào.
- props là các tham số truyền vào React Component. props được truyền vào Component thông qua các HTML attributes.
- Chúng ta sử dụng props để gửi dữ liệu đến component.
- Trong React, props tương đương với các tham số của hàm JavaScrip thông thường.
- Các giá trị của props không bị thay đổi, khi muốn thay đổi trạng thái của component thì người ta chỉ thay đổi state của component chứ props thì không thay đổi được.
Đây là 1 ví dụ về props
2.4 State:
State cho phép chúng ta lưu trữ dữ liệu trong component, và mỗi khi state thay đổi thì component đó sẽ tự động re-render.
State là một object có thể được sử dụng để chứa dữ liệu hoặc thông tin về components. State có thể được thay đổi bất cứ khi nào mong muốn. Khác với props bạn có thể truyền props sang các components khác nhau thì state chỉ tồn tại trong phạm vi của components chứa nó, mỗi khi state thay đổi thì components đó sẽ được render lại.
Sau đây là 1 số thao tác với state trong React
Ví dụ bên dưới ta có một class components và tiến hành khởi tạo state bên trong phương thức constructor:
Như đã nói ở phần trên, chúng ta nên khởi tạo state trong constructor.
- Cập nhật state
Để cập nhật một state ta sử dụng phương thức:
Hoặc cũng có thể lấy giá trị của state trước khi cập nhật:
Sau đây sẽ là 1 số tổng kết về sự khác nhau giữa props và state:
- State – Dữ liệu chỉ nằm trong phạm vi của một component. Nó được sở hữu bởi một components cụ thể mà chỉ là của component đó thôi. Và mỗi khi state thay đổi thì component cũng phải thay đổi theo.
- Props – Dữ liệu đường truyền từ component cha cho componet con, components con khi nhận được sẽ chỉ được đọc mà không thể thay đổi dữ liệu đó.
2.5 React Component Lifecycle:
Trước tiên, chúng ta hãy cùng nhìn qua 1 lượt sơ đồ của component lifecycle
Có thể chia các phương thức lifecycle ra 3 nhóm, ứng với 4 giai đoạn của component: Mounting, Updating, Unmounting, Error Handling.
Mounting: Gồm thứ tự như sau
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
Updating: Các phương thức này sẽ được gọi khi có sự thay đổi của state hoặc props.
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
Unmounting: Phương thức được gọi trước khi remove component khỏi DOM.
- componentWillUnmount()
Error Handling: Bất kể lỗi ở đâu trong component, nó sẽ gọi đến phương thức này.
- componentDidCatch()
Giờ hãy cùng đi vào chi tiết của các phương thức trên
constructor(props):
Như đã được nêu chi tiết ở phần 2.2, nên giờ tôi chỉ nói sơ lại 1 lần nữa. Đây là phương thức khởi tạo một component, nếu không khởi tạo state, bind các phương thức, thì ko cần khai báo phương thức này.
render():
Đây là phương thức bắt buộc duy nhất khi tạo ra một component, bắt buộc trả về một trong những giá trị
- React element
- Arrays and fragments
- Portals
- String and numbers
- Booleans or null
Chú ý: Hàm này sẽ không được gọi nếu shouldComponentUpdate()
return false.
componentDidMount():
- Ngay sau khi hàm render được gọi đến lần đầu tiên thì hàm này sẽ được chạy.
- Thường dùng để fetch dữ liệu từ server và sau đó setState để render dữ liệu ra.
- Đến đây thì các phần tử đã được sinh ra rồi, và có thể tương tác với DOM bằng JS trong hàm này.
Ví dụ:
Ở đây, chúng ta sẽ fetch data từ 1 resource khác và setState cho dữ liệu sau khi lấy về.
componentDidUpdate(prevProps, prevState, snapshot)
- Khi một component instance update, componentDidUpdate sẽ được gọi sau khi render HTML được loading xong.
- componentDidUpdate tự động được truyền vào 2 argument là prevProps và prevState. prevProps và prevState sẽ tham chiếu đến prop và state của component trước khi quá trình update component bắt đầu. Chúng ta có thể so sánh 2 arguments này với giá trị hiện tại của prop và state. componentDidUpdate thường được sử dụng để tương tác với một số thứ bên ngoài vào môi trường React như là browser hay APIs.
componentWillUnmount()
- Được gọi khi 1 component được loại bỏ khỏi DOM.
- Thực hiện các thao tác dọn dẹp như huỷ các timer, loại bỏ các phần tử thừa
Hãy cùng xem ví dụ sau đây, method này sẽ được gọi ngay sau khi component User bị destroy
shouldComponentUpdate(nextProps, nextState)
- Có phương thức này để cải thiện performance của React, vì đôi lúc thay đổi state hoặc props ta không muốn cập nhập lại UI, chỉ cần cho hàm này return false (mặc định là return true), khi return false thì render, componentDidUpdate sẽ không được gọi.
Ví dụ:
Chúng ta có thể thấy React giữ trạng thái đếm mỗi lần nhấp vào button và cũng lưu giá trị được chọn ngẫu nhiên (true, fasle). Tuy nhiên, nhờ vào phương thức ShouldComponentUpdate, component chỉ được render lại nếu state.value !== state.value mới.
getDerivedStateFromProps(props, state)
- React 16.3 đã giới thiệu 1 function mới trong vòng đời đó là getDerivedStateFromProps.
- Nó thay thế componentWillReceiveProps, bắt đầu từ React 17 sẽ không còn hỗ trợ nữa bởi đôi khi bị sử dụng sai và không phù hợp với rendering đồng bộ.
- Nó giúp thay đổi this.state khi props thay đổi. Đây là một phương thức tĩnh, được khai báo như sau:
- Vì là phương thức tĩnh nên trong hàm getDerivedStateFromProps ta không thể dùng this hay gọi đến this.setState(). Do đó, sau khi thực hiện so sánh và phát hiện cần re-render, ta chỉ trả về một object chứa các thay đổi của state dựa vào props. Thay đổi này sẽ được merge vào this.state. Ngược lại nếu không muốn thực hiện re-render, trả về null.
getSnapshotBeforeUpdate(prevProps, prevState)
- Hàm này được thực thi ngay sau khi update component. Hàm này lấy trạng thái trước khi update để xử lý.
- Nó là đầu vào cho componentDidUpdate (cá giá trị return từ hàm này sẽ đưa cho componentDidUpdate).
componentDidCatch(error, info)
- Nếu bất kỳ 1 component nào bị lỗi thì khi sử dụng hàm này, app sẽ không bị crash mà sẽ quăng lỗi lên trên này và hiển thị ra view
Tổng kết:
- Như vậy là chúng ta đã đi nhanh qua vòng đời và 1 số method chính trong vòng đời của React, các bạn có thể tham khảo thêm tại đây: https://reactjs.org/docs/react-component.html
3. Thực hành tạo 1 app Todo List đơn giản
Chúng ta sẽ cùng tạo ra 1 app ToDo List đơn giản với các chức năng cơ bản như tạo mới event, đánh dấu đã hoàn thành event và xóa event.
3.1 Khởi tạo constructor:
- Data chúng ta sẽ sử dụng 2 params (todoItems, error) trong local state để lưu cũng như render event. Ngoài ra chúng ta cũng sẽ bind tới các events trong các components con.
- Format của data
[ { title: 'Title of event', completed: true // boolean: True/False } ]
3.2 Sử dụng method componentDidMount để fetch data:
- Như đã nói ở phần vòng đời của component, chúng ta sẽ sử dụng componentDidMount() để fetch data (hoặc có thể gọi ajax connect tới API, …).
3.3 Các component con
- Component TodoHeader
- Component TodoForm
- Component TodoList
- Component TodoListItem
- Component TodoApp
3.4 Kết quả:
Demo: https://jsfiddle.net/nhupham95/f9nxm2td/48/
Github: https://github.com/ceresgiang/ceres-front-end/tree/react-todo-api/src/nhupham
4. Tổng kết
Qua bài viết này, tôi muốn chia sẽ đến các bạn một số kiến thức cơ bản của React để chúng ta có thể làm quen và dễ tiếp xúc hơn với nó. Cảm ơn tất cả các bạn đã giành thời gian để đọc bài viết này, xin chân thành cảm ơn!