Tiếp nối phần 1, mời bạn đón xem phần 2 của chủ đề: Lifecycle của một component trong React!
Nội dung bài viết
Cập nhật thông tin
Xem lại Phần 1 : Lifecycle của một component trong React
Đầu năm 2018, nhóm tăng trưởng React đã đưa ra 1 số ít yếu tố cần đổi khác để đáp ứng render bất đông bộ. Một số yếu tố về lifecycle được phát hiện và đã tìm ra giải pháp khắc phục .
Một trong những vấn đề lớn nhất là khi thực hiện các câu lệnh trong một số hàm của lifecycle không được an toàn. Một số hàm trong giai đoạn trước khi render bị hiểu sai và lạm dụng. Hơn nữa, việc sử dụng sai chức năng có thể gây ra nhiều vấn đề hơn khi render bất đồng bộ. Ví thế, React quyết định thêm tiền tố “UNSAFE_” vào tên các phương thức trong các phiên bản React sau này.
Đổi tên một số lifecycle
React không vô hiệu giật mình bất thần những lifecyle không bảo vệ bảo đảm an toàn, mà tổng thể tất cả chúng ta sẽ được cảnh báo nhắc nhở nhắc nhở và vô hiệu từ từ trong những phiên bản React, đơn cử là 3 giải pháp :
- componentWillMount()
- componentWillReceiveProps()
- componentWillUpdate()
16.3: React giới thiệu về các phương thức unsafe lifecycle: UNSAFE_componentWillMount(), UNSAFE_componentWillReceiveProps(), UNSAFE_componentWillUpdate(). Ở phiên bản này, cả hai tên phương thức cũ và mới đều sẽ làm việc bình thường.
16.3+: React bật cảnh báo trong console.log (DEV-mode warning) khi ta sử dụng các phương thức trên với tên cũ mà không có tiền tố “UNSAFE_”. Cả hai tên phương thức cũ và mới vẫn sẽ làm việc bình thường.
Warning khi sử dụng componentWillMount() không có tiền tố “UNSAFE_”
Warning khi sử dụng componentWillReceiveProps() không có tiền tố “UNSAFE_”
Warning khi sử dụng componentWillUpdate() không có tiền tố “UNSAFE_”
17.0: Ở phiên bản này trở đi, React sẽ loại bỏ hoàn toàn tên cũ của 3 phương thức trên. Chỉ khi sử dụng tên mới với “UNSAFE_ ” thì mới có thể hoạt động, nếu không sẽ gây ra lỗi.
Ghi chú: Nếu dự án của chúng ta đang sử dụng phiên bản React <17.0 thì những tên phương thức cũ được nêu trên vẫn hoạt động bình thường, không cần phải viết lại chúng ngay lập tức. Chỉ khi bạn muốn cập nhật để sử dụng phiên bản >=17.0 thì mới cần thiết đổi tên, React khuyên dùng lệnh ‘codemod” để có thể tự động chuyển đổi tên theo đúng chuẩn của họ.
cd your_project
npx react-codemod rename-unsafe-lifecycles
Các Lifecycle mới
Trong phiên bản 16.3, ngoài việc ra mắt 3 phương thức đã được đổi tên như trên, React có thêm 2 hàm trong lifecycle mới là getDerivedStateFromProps() và getSnapshotBeforeUpdate(), 2 phương thức mới này đều nằm trong giai đoạn Updating của một component.
Phương thức getDerivedStateFromProps()
Chúng ta hiểu nôm na phương pháp này là “ nhận state mới được tạo ra bởi props “ .
ADVERTISEMENTHàm render được khởi chạy khi xảy ra 2 trường hợp sau :
- Trường hợp 1: Khi ta gọi hàm setState để cập nhật lại state trong component.
- Trường hợp 2: Khi component đó là con có props được truyền vào từ component cha bị thay đổi.
Phương thức này được sử dụng ở trường hợp thứ 2, được khởi chạy trước khi component được re-render ( render lần thứ 2 trở đi ). Hàm này có 2 arguments là nextProps ( props mới được biến hóa ) và currentState ( state hiện tại của component ) .
Mặc định nếu props đổi khác thì component sẽ re-render. Nhưng có một trường hợp là được props đổi khác nhưng component con không nhận ra được để re-render, đó là tất cả chúng ta khởi tạo state bằng chính props. Ví dụ :
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = { gender: "" };
}
handleChangeGender = (event) => {
this.setState({ gender: event.target.value });
};
render() {
return (
<>
Select your gender:
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = { name: props.gender };
}
handleChange = (event) => {
this.setState({ gender: event.target.value });
};
render() {
return (
<>
Input your name:
Hello! {this.state.name}
);
}
}
Theo ví dụ trên, ChildComponent có một state là ‘ name ’ được gán bằng ‘ props.gender ’ trong hàm constructor ( ). Cách này làm cho component không nhận ra được khi nào props được đổi khác. Lúc đó, toàn bộ tất cả chúng ta cần sử dụng hàm getDerivedStateFromProps ( ) để bắt được sự biến hóa của this.props, tổng thể tất cả chúng ta so sánh nextProps và currentState để update lại state với giá trị props được biến hóa. Thêm đoạn code sau dưới hàm constructor trong ví dụ để trọn vẹn hoàn toàn có thể update lại state :
static getDerivedStateFromProps = (nextProps, currentState) => {
// Bất cứ lúc nào props.gender thay đổi thì cập nhật lại state.
if (nextProps.gender !== currentState.name) {
return {
name: nextProps.gender,
};
}
// Trả về rỗng để biểu thị không có cập nhật state
return null;
};
Ghi chú : Hạn chế gán giá trị của props vào lúc khởi tạo state để đơn giản hóa component và tránh xảy ra lỗi .
Phương thức getSnapshotBeforeUpdate()
Hàm này được khởi chạy trước khi component re-render thành công xuất sắc. Chạy sau hàm render ( ) nhưng trước hàm componentDidUpdate ( ). Giá trị được trả về trong quá trình này được truyền vào argument thứ 3 ( snapshot ) của componentDidUpdate ( ) .
Xét ví dụ sau để xem cách sử dụng của hàm này. Đề bài là khi tất cả chúng ta thêm tin nhắn vào list log, nếu list quá dài thì thanh scroll Open, sau đó thanh scroll sẽ tự động hóa scroll đến dòng mới nhất vừa được thêm vào :
class PostLog extends React.Component {
constructor(props) {
super(props);
this.state = {
t: 0,
messages: [],
};
this.chatRef = React.createRef();
}
componentDidMount() {
this.timerID = setInterval(() => this.addMessage(), 500);
}
addMessage() {
let { messages, t } = this.state;
if (messages.length < 1000) {
const newMessage = `Datetime: ${new Date().toISOString()} added log ${t}`;
messages = [...messages, newMessage];
t++;
this.setState({ messages, t });
}
}
renderMessage(msg, i) {
return {msg} ;
}
render() {
return (
Message Log
{this.state.messages.map((msg, i) => {
return this.renderMessage(msg, i);
})}
);
}
}
Ví dụ trên, một log sẽ được tự động hóa thêm vào mỗi 500 ms. Và ta sẽ thấy Open thanh scroll, nhưng không tự động hóa scroll xuống log mới nhất. Thêm đoạn code sau bên dưới hàm componentDidMount ( ) để thấy được sự biến hóa :
// Hàm này sẽ trả về biến 'snapshot' trước khi DOM update thành công.
getSnapshotBeforeUpdate(prevProps, prevState) {
const { current } = this.chatRef;
const isScrolledToBottom =
current.scrollTop + current.offsetHeight >= current.scrollHeight;
return { isScrolledToBottom };
}
// Recieve the snapshot and check if the user is scrolled to the bottom of the log
// Hàm này nhận argument 'snapshot' và update lại vị trí scroll của element mới nhất.
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot.isScrolledToBottom) {
this.chatRef.current.scrollTop = this.chatRef.current.scrollHeight;
}
}
Kết quả hiển thị như sau :
Demo GetDerivedStateFromProps()Phương thức getSnapshotBeforeUpdate ( ) có 2 arguments là prevProps ( props trước đó ) và prevState ( state trước đó ) và trả về là một giá trị bất kể. Hàm này không hoạt động giải trí riêng không liên quan gì đến nhau mà phối hợp sử dụng với componentDidUpdate ( ) .
Bên trên là những biến hóa về những phương pháp mới lẫn cũ của lifecycle. Hy vọng bài viết này sẽ hữu dụng với bạn. Cám ơn những bạn đã theo dõi bài viết .
Bài viết có tìm hiểu thêm thông tin từ link : https://vi.reactjs.org/blog/2018/03/27/update-on-async-rendering.html
CÔNG TY CỔ PHẦN TẬP ĐOÀN TINO
- Trụ sở chính: L17-11, Tầng 17, Tòa nhà Vincom Center, Số 72 Lê Thánh Tôn, Phường Bến Nghé, Quận 1, Thành phố Hồ Chí Minh
Văn phòng đại diện: 42 Trần Phú, Phường 4, Quận 5, Thành phố Hồ Chí Minh - Điện thoại: 0364 333 333
Tổng đài miễn phí: 1800 6734 - Email: [email protected]
- Website: www.tino.org
Source: https://swing.com.vn
Category: Wiki