ReactJS: Lifecycle của 1 element trong React (Phần 2)

Tiếp nối phần 1, mời bạn đón xem phần 2 của chủ đề: Lifecycle của 1 element trong React!

Cập nhật thông tin

Xem lại Phần 1: Lifecycle của 1 element trong React

Đầu 5 2018, nhóm vươn lên là React đã đưa ra 1 số vấn đề cần thay đổi để đáp ứng render bất đông bộ. 1 số vấn đề về lifecycle được phát hiện và đã tìm ra giải pháp khắc phục.

1 trong những vấn đề lớn nhất là lúc thực hành những câu lệnh trong 1 số hàm của lifecycle ko được an toàn. 1 số hàm trong giai đoạn trước lúc render bị hiểu sai và lạm dụng. Hơn nữa, việc dùng sai chức năng có thể gây ra nhiều vấn đề hơn lúc render bất đồng bộ. Ví thế, React quyết định thêm tiền tố “UNSAFE_” vào tên những phương thức trong những phiên bản React sau này.

Đổi tên 1 số lifecycle

React ko loại bỏ đột ngột những lifecyle ko an toàn, mà chúng ta sẽ được cảnh báo và loại bỏ dần dần trong những phiên bản React, cụ thể là 3 phương thức:

  • componentWillMount()
  • componentWillReceiveProps()
  • componentWillUpdate()

16.3: React giới thiệu về những phương thức unsafe lifecycle: UNSAFE_componentWillMount(), UNSAFE_componentWillReceiveProps(), UNSAFE_componentWillUpdate(). Ở phiên bản này, cả 2 tên phương thức cũ và mới đều sẽ khiến việc bình thường.

16.3+: React bật cảnh báo trong console.log (DEV-mode warning) lúc ta dùng những phương thức trên có tên cũ mà ko có tiền tố “UNSAFE_”. Cả 2 tên phương thức cũ và mới vẫn sẽ khiến việc bình thường.

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ỉ lúc dùng tên mới có “UNSAFE_ ” thì mới có thể hoạt động, trường hợp ko sẽ gây ra lỗi.

Xem Thêm  SEC có đang 'để dành' BTC và ETH cho trận đấu cuối cùng?

Ghi chú: Ví dụ dự án của chúng ta đang 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, ko cần nên viết lại chúng ngay tức khắc. Chỉ lúc bạn muốn cập nhật để 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

Những Lifecycle mới

Trong phiên bản 16.3, bên cạnh 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()getSnapshotBeforeUpdate(), 2 phương thức mới này đều nằm trong giai đoạn Updating của 1 element.

Phương thức getDerivedStateFromProps()

Chúng ta hiểu nôm na phương thức này là “nhận state mới được tạo ra bởi props“.

Hàm render được khởi chạy lúc xảy ra 2 trường hợp sau:

  • Trường hợp 1: Lúc ta gọi hàm setState để cập nhật lại state trong element.
  • Trường hợp 2: Lúc element đấy là con có props được truyền vào từ element cha bị thay đổi.

Phương thức này được dùng ở trường hợp thứ 2, được khởi chạy trước lúc element được re-render (render lần thứ 2 trở đi). Hàm này có 2 arguments là nextProps (props mới được thay đổi) và currentState (state hiện tại của element).

Mặc định trường hợp props thay đổi thì element sẽ re-render. Nhưng có 1 trường hợp là được props thay đổi nhưng element con ko nhận biết được để re-render, đấy là chúng ta khởi tạo state bằng chính props. Thí dụ:

class ParentComponent extends React.Part { constructor(props) { tremendous(props); this.state = { gender: “” }; } handleChangeGender = (occasion) => { this.setState({ gender: occasion.goal.worth }); }; render() { return ( <> <hr /> <label htmlFor=”gender”> Choose your gender: </label> <choose title=”gender” onChange={this.handleChangeGender}> <possibility worth=””>-Choose-</possibility> <possibility worth=”male”>Male</possibility> <possibility worth=”feminine”>Feminine</possibility> </choose> <hr /> <Enter gender={this.state.gender} /> </> ); } } class ChildComponent extends React.Part { constructor(props) { tremendous(props); this.state = { title: props.gender }; } handleChange = (occasion) => { this.setState({ gender: occasion.goal.worth }); }; render() { return ( <> <label htmlFor=”title”> Enter your title: </label> <enter title=”title” onChange={this.handleChange} worth={this.state.title} /> <hr /> <h2>Hiya! {this.state.title}</h2> </> ); } }

Xem Thêm  Maverick Protocol (MAV) là gì? Dự án Binance Launchpool lần thứ 34

Theo dí dụ trên, ChildComponent có 1 state là ‘title’ được gán bằng ‘props.gender’ trong hàm constructor(). Phương pháp này khiến cho element ko nhận biết được lúc nào props được thay đổi. Lúc đấy, chúng ta cần dùng hàm getDerivedStateFromProps() để bắt được sự thay đổi của this.props, chúng ta so sánh nextProps và currentState để cập nhật lại state có giá trị props được thay đổi. Thêm đoạn code sau dưới hàm constructor trong dí dụ để có thể cập nhật 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.title) { return { title: nextProps.gender, }; } // Trả về rỗng để biểu thị ko 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 element và hạn chế xảy ra lỗi.

Phương thức getSnapshotBeforeUpdate()

Hàm này được khởi chạy trước lúc element re-render thành công. Chạy sau hàm render() nhưng trước hàm componentDidUpdate(). Giá trị được trả về trong giai đoạn này được truyền vào argument thứ 3 (snapshot) của componentDidUpdate().

Xét dí dụ sau để xem phương pháp dùng của hàm này. Đề bài là lúc chúng ta thêm tin nhắn vào danh sách log, trường hợp danh sách quá dài thì thanh scroll xuất hiện, sau đấy thanh scroll sẽ tự động scroll tới dòng mới nhất vừa được thêm vào:

class PostLog extends React.Part { constructor(props) { tremendous(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.size < 1000) { const newMessage = `Datetime: ${new Date().toISOString()} added log ${t}`; messages = […messages, newMessage]; t++; this.setState({ messages, t }); } } renderMessage(msg, i) { return <li key={i}>{msg}</li>; } render() { return ( <React.Fragment> <h1>Message Log</h1> <div ref={this.chatRef} className=”log”> <ul> {this.state.messages.map((msg, i) => { return this.renderMessage(msg, i); })} </ul> </div> </React.Fragment> ); } }

Xem Thêm  Outlook mail là gì? Phương pháp cài đặt mail Outlook trên máy tính

Thí dụ trên, 1 log sẽ được tự động thêm vào mỗi 500ms. Và ta sẽ thấy xuất hiện thanh scroll, nhưng ko tự động 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ự thay đổi:

// Hàm này sẽ trả về biến ‘snapshot’ trước lúc DOM replace thành công. getSnapshotBeforeUpdate(prevProps, prevState) { const { present } = this.chatRef; const isScrolledToBottom = present.scrollTop + present.offsetHeight >= present.scrollHeight; return { isScrolledToBottom }; } // Recieve the snapshot and verify if the consumer is scrolled lớn the underside of the log // Hàm này nhận argument ‘snapshot’ và replace lại vị trí scroll của ingredient mới nhất. componentDidUpdate(prevProps, prevState, snapshot) { if (snapshot.isScrolledToBottom) { this.chatRef.present.scrollTop = this.chatRef.present.scrollHeight; } }

Kết quả hiển thị như sau:

Phương thức getSnapshotBeforeUpdate() có 2 arguments là prevProps (props trước đấy) và prevState (state trước đấy) và trả về là 1 giá trị bất kì. Hàm này ko hoạt động riêng lẻ mà hài hòa dùng có componentDidUpdate().

Bên trên là những thay đổi về những phương thức mới lẫn cũ của lifecycle. Hy vọng bài viết này sẽ hữu ích có bạn. Cám ơn khách hàng đã theo dõi bài viết.

Bài viết có tham khảo thông tin từ hyperlink: https://vi.reactjs.org/weblog/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 Middle, Số 72 Lê Thánh Tôn, Phường Bến Nghé, Quận 1, Thành phố Hồ Chí MinhVă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 333Tổng đài miễn phí tổn: 1800 6734
  • E-mail: gross [email protected]
  • Web site: www.tino.org