Khi muốn render lại một component, chúng ta cần thay đổi lại dữ liệu (có thể là props hoặc state). Ở bài viết trước, chúng ta đã tìm hiểu về props của một component. Trong bài viết này, Tino Group sẽ giới thiệu thêm về khái niệm state và cách sử dụng state đúng cách trong một component như thế nào nhé!
Giới thiệu về State
State là gì?
State cũng tương tự như props, nhưng nó là của riêng một component và được quản lý bởi chính component đó.
Có thể xem state giống như nơi lưu trữ dữ liệu của một component trong React. Nó được dùng chủ yếu để cập nhật lại giao diện (UI) với các điều kiện nhất định.
Để sử dụng được state thì component của chúng ta phải là một class component (hoặc có thể sử dụng React Hooks trong phiên bản 16.8).
Class component thì được kế thừa từ lớp cơ sở của React là React.Component. Trong một component, state giá trị ban đầu là null, và được khai báo trong hàm khởi tạo (Constructor), và chúng ta có thể gán giá trị mặc định của state ở hàm này.
Ví dụ về State
Xem ví dụ sau để hiểu rõ hơn về state, yêu cầu là bài viết ban đầu chỉ hiển thị phần mô tả ngắn, sau khi nhấn nút “View more” thì mới hiển thị tất cả nội dung bài viết đồng thời ẩn đi nút ‘View more’:
Giải thích ví dụ:
- Component WikiPost là một class kế thừa từ lớp Component của React nên chúng ta có thể khai báo và quản lý state trong này.
- Component này có hàm khởi tạo (constructor), trong đó chúng ta khởi tạo một state có key là ‘viewmore’, giá trị là false.
- Để sử dụng được giá trị bên trong state ta dùng this.state.
- Component này sẽ trả về giá trị là các elements tags và hiển thị chúng trên trình duyệt như sau:
- Khi chúng ta nhấn vào nút “View more”, thì component sẽ lắng nghe đến hàm handleViewmore(), trong hàm này ta dùng phương thức setState() để cập nhật lại giá trị viewmore của state.
- Giá trị được cập nhật thì component của chúng ta sẽ được render lại, và hiển thị tiếp đoạn văn bản đúng với yêu cầu. Kết quả như sau:
Chuyển đổi Function component thành Class component
Để sử dụng state, các phương thức lifecycle và các tác vụ khác, ta phải chuyển function component thành class component, hãy xem qua các bước đơn giản sau để chuyển đổi nhé:
Bước 1: Tạo một class ES6 cùng tên với function cần chuyển, và cho class đó kế thừa lớp cơ sở React.Component.
Bước 2: Thêm một phương thức render() rỗng trong class.
Bước 3: Di chuyển nội dung của function vào bên trong phương thức render()
Bước 4: Thay thế props bằng this.props trong nội dung của render() nếu có.
Bước 5: Xóa function rỗng ban đầu.
function DetailPost(props) {
return <h1>Title: {props.title}</h1>;
}
class DetailPost extends React.Component {
render() {
return <h1>Title: {this.props.title}</h1>;
}
}
Sử dụng state đúng cách như thế nào?
Không cập nhật trực tiếp giá trị của state
Để cập nhật lại giá trị của state, chúng ta không thể gán giá trị trực tiếp vào state như this.state = {‘key’: ‘new value’}, mà buộc phải sử dụng phương thức setState() của React.
Nơi duy nhất bạn có thể gán this.state là ở hàm khởi tạo (constructor).
Cập nhật state có thể là bất đồng bộ (Asynchronous)
Bởi vì this.state và this.props có thể được cập nhật bất đồng bộ, nên khi chúng ta dựa vào giá trị của chúng để tính toán state tiếp theo thì nhiều trường hợp sẽ bị sai.
State cập nhật những biến độc lập
State gộp object ta cung cấp vào state hiện tại khi ta gọi setState().
Khi state là một object chứa nhiều key, thì khi gọi setState(), state chỉ cập nhật những key với value được truyền vào và giữ nguyên các key còn lại.
Ví dụ, ta khai báo một state với các key độc lập:
constructor(props) {
super(props);
this.state = {
comments: [],
tags: [],
author: ''
};
}
Sau đó ta chỉ cập nhật giá trị cho key cần thiết:
this.setState({
tags: ['react', 'post']
});
React sẽ so sánh object được truyền vào hàm setState() với state hiện tại một cách shallow (so sánh nông), nên khi đó chỉ key tags được cập nhật lại giá trị mới, các key còn lại sẽ được giữ nguyên giá trị cũ.
Chuyển state thành props
State được gọi là biến cục bộ và được khép kín trong một component, nên một component khác muốn truy cập đến state của một component khác là điều không thể.
Một component cha có thể truyền state của chính nó xuống một component con như một props để component con có thể sử dụng. Ví dụ:
function DetailPost() {
return <h1>Title: {this.props.title}</h1>;
}
class WikiPost extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "",
};
}
render() {
return <DetailPost title={this.state.title} />;
}
}
Component con DetailPost sẽ nhận title trong props của nó từ state của component cha WikiPost. Khi title ở state của component cha thay đổi, props của component con sẽ thay đổi theo. Vì thế, cả component WikiPost và DetailPost đều sẽ được render lại.
Đây được gọi là luồng dữ liệu ‘top-down’ hoặc ‘unidirectional’.
Lưu ý: Mỗi khi giá trị của state hoặc props thay đổi thì component sẽ được render lại.
Nhưng có những lúc chúng ta cập nhật state nhưng không muốn phải render lại component thì sao? Việc này sẽ được xử lý trong các lifecycle của component. Bạn có thể tìm hiểu về life cycle của một component trong React ở bài viết sau.
Bài viết có tham khảo thông tin tại link: https://reactjs.org/docs/state-and-lifecycle.html