Thứ năm, 01/10/2020 | 00:00 GMT+7

Cách xử lý khi tải dữ liệu không đồng bộ, tải chậm và phân tách mã bằng React

Là một nhà phát triển web JavaScript , mã không đồng bộ cung cấp cho bạn khả năng chạy một số phần mã của bạn trong khi các phần khác vẫn đang chờ dữ liệu hoặc giải quyết. Điều này nghĩa là các phần quan trọng trong ứng dụng của bạn sẽ không phải đợi các phần ít quan trọng hơn trước khi chúng hiển thị. Với mã không đồng bộ, bạn cũng có thể cập nhật ứng dụng của bạn bằng cách yêu cầu và hiển thị thông tin mới, mang lại cho user trải nghiệm mượt mà ngay cả khi các chức năng và yêu cầu dài đang xử lý ở chế độ nền.

Trong phát triển React , lập trình không đồng bộ đưa ra các vấn đề duy nhất. Ví dụ, khi bạn sử dụng các thành phần chức năng React, các chức năng không đồng bộ có thể tạo ra các vòng lặp vô hạn. Khi một thành phần tải, nó có thể bắt đầu một chức năng không đồng bộ và khi chức năng không đồng bộ giải quyết, nó có thể kích hoạt kết xuất lại khiến thành phần đó gọi lại chức năng không đồng bộ. Hướng dẫn này sẽ giải thích cách tránh điều này với một Hook đặc biệt được gọi là useEffect , sẽ chỉ chạy các chức năng khi dữ liệu cụ thể thay đổi. Điều này sẽ cho phép bạn chạy mã không đồng bộ của bạn một cách có chủ ý thay vì trên mỗi chu kỳ hiển thị.

Mã không đồng bộ không chỉ giới hạn ở các yêu cầu về dữ liệu mới. Phản ứng đã tích hợp sẵn trong hệ thống cho các thành phần tải lười biếng, hoặc tải chúng chỉ khi người sử dụng cần chúng. Khi được kết hợp với cấu hình webpack mặc định trong Create React App , bạn có thể chia nhỏ mã của bạn , giảm một ứng dụng lớn thành các phần nhỏ hơn để có thể tải khi cần thiết. React có một thành phần đặc biệt gọi là Suspense sẽ hiển thị các trình giữ chỗ trong khi trình duyệt đang tải thành phần mới của bạn. Trong các version React trong tương lai, bạn có thể sử dụng Suspense để tải dữ liệu trong các thành phần lồng nhau mà không bị chặn hiển thị.

Trong hướng dẫn này, bạn sẽ xử lý dữ liệu không đồng bộ trong React bằng cách tạo một ứng dụng hiển thị thông tin về các sông và mô phỏng các yêu cầu tới API Web bằng setTimeout . Đến cuối hướng dẫn này, bạn có thể tải dữ liệu không đồng bộ bằng useEffect Hook. Bạn cũng sẽ có thể cập nhật trang một cách an toàn mà không tạo ra lỗi nếu thành phần ngắt kết nối trước khi phân giải dữ liệu. Cuối cùng, bạn sẽ chia một ứng dụng lớn thành các phần nhỏ hơn bằng cách sử dụng tách mã.

Yêu cầu

Bước 1 - Tải dữ liệu không đồng bộ bằng useEffect

Trong bước này, bạn sẽ sử dụng useEffect Hook để tải dữ liệu không đồng bộ vào một ứng dụng mẫu. Bạn sẽ sử dụng Hook để ngăn tìm nạp dữ liệu không cần thiết, thêm trình giữ chỗ trong khi dữ liệu đang tải và cập nhật thành phần khi dữ liệu phân giải. Đến cuối bước này, bạn có thể tải dữ liệu bằng useEffect và cài đặt dữ liệu bằng useState Hook khi nó được giải quyết.

Để khám phá chủ đề này, bạn sẽ tạo một ứng dụng để hiển thị thông tin về những con sông dài nhất trên thế giới. Bạn sẽ tải dữ liệu bằng một hàm không đồng bộ mô phỏng một yêu cầu đến nguồn dữ liệu bên ngoài.

Đầu tiên, tạo một thành phần có tên là RiverInformation . Tạo folder :

  • mkdir src/components/RiverInformation

Mở RiverInformation.js trong editor :

  • nano src/components/RiverInformation/RiverInformation.js

Sau đó, thêm một số nội dung giữ chỗ:

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React from 'react';  export default function RiverInformation() {   return(     <div>       <h2>River Information</h2>     </div>   ) } 

Lưu và đóng file . Đến đây bạn cần nhập và kết xuất thành phần mới thành thành phần root của bạn. Mở App.js :

  • nano src/components/App/App.js

Nhập và hiển thị thành phần bằng cách thêm vào mã được đánh dấu:

async-tutorial / src / components / App / App.js
import React from 'react'; import './App.css'; import RiverInformation from '../RiverInformation/RiverInformation';  function App() {   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <RiverInformation />     </div>   ); }  export default App; 

Lưu và đóng file .

Cuối cùng, để giúp ứng dụng dễ đọc hơn, hãy thêm một số kiểu. Mở App.css :

  • nano src/components/App/App.css

Thêm một số đệm vào lớp wrapper bằng cách thay thế CSS bằng như sau:

async-tutorial / src / components / App / App.css
.wrapper {     padding: 20px } 

Lưu và đóng file . Khi bạn làm như vậy, trình duyệt sẽ làm mới và hiển thị các thành phần cơ bản.

Thành phần cơ bản, 1

Trong hướng dẫn này, bạn sẽ tạo các dịch vụ chung để trả lại dữ liệu. Dịch vụ đề cập đến bất kỳ mã nào được dùng lại để hoàn thành một nhiệm vụ cụ thể. Thành phần của bạn không cần biết cách dịch vụ lấy thông tin của nó. Tất cả những gì nó cần biết là dịch vụ sẽ trả về một Lời hứa . Trong trường hợp này, yêu cầu dữ liệu sẽ được mô phỏng bằng setTimeout , yêu cầu này sẽ đợi trong một khoảng thời gian xác định trước khi cung cấp dữ liệu.

Tạo một folder mới được gọi là services trong folder src/ :

  • mkdir src/services

Thư mục này sẽ chứa các chức năng không đồng bộ của bạn. Mở file có tên rivers.js :

  • nano src/services/rivers.js

Bên trong file , xuất một hàm có tên getRiverInformation trả về một lời hứa. Bên trong lời hứa, hãy thêm một hàm setTimeout sẽ giải quyết lời hứa sau 1500 mili giây. Điều này sẽ cho bạn một chút thời gian để xem thành phần sẽ hiển thị như thế nào trong khi chờ dữ liệu được giải quyết:

async-tutorial / src / services / rivers.js
export function getRiverInformation() {   return new Promise((resolve) => {     setTimeout(() => {       resolve({         continent: 'Africa',         length: '6,650 km',         outflow: 'Mediterranean'       })     }, 1500)   }) } 

Trong đoạn mã này, bạn đang mã hóa thông tin sông, nhưng hàm này sẽ tương tự với bất kỳ hàm không đồng bộ nào mà bạn có thể sử dụng, chẳng hạn như lệnh gọi API. Phần quan trọng là mã trả về một lời hứa.

Lưu và đóng file .

Đến đây bạn có một dịch vụ trả về dữ liệu, bạn cần thêm nó vào thành phần của bạn . Điều này đôi khi có thể dẫn đến một vấn đề. Giả sử bạn đã gọi hàm không đồng bộ bên trong thành phần của bạn và sau đó đặt dữ liệu thành một biến bằng useState Hook. Mã sẽ như thế này:

import React, { useState } from 'react'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation() {   const [riverInformation, setRiverInformation] = useState({});    getRiverInformation()   .then(d => {     setRiverInformation(d)   })    return(     ...   ) } 

Khi bạn đặt dữ liệu, thay đổi Hook sẽ kích hoạt kết xuất lại các thành phần. Khi thành phần kết xuất lại, hàm getRiverInformation sẽ chạy lại và khi nó được giải quyết, nó sẽ cài đặt trạng thái, điều này sẽ kích hoạt một kết xuất lại khác. Vòng lặp sẽ tiếp tục mãi mãi.

Để giải quyết vấn đề này, React có một Hook đặc biệt gọi là useEffect sẽ chỉ chạy khi dữ liệu cụ thể thay đổi.

useEffect Hook chấp nhận một hàm làm đối số đầu tiên và một mảng trình kích hoạt làm đối số thứ hai. Chức năng sẽ chạy trong lần hiển thị đầu tiên sau khi bố trí và tô. Sau đó, nó sẽ chỉ chạy nếu một trong các trình kích hoạt thay đổi. Nếu bạn cung cấp một mảng trống, nó sẽ chỉ chạy một lần. Nếu bạn không bao gồm một loạt các trình kích hoạt, nó sẽ chạy sau mỗi lần hiển thị.

Mở RiverInformation.js :

  • nano src/components/RiverInformation/RiverInformation.js

Sử dụng useState Hook để tạo một biến có tên là riverInformation và một hàm được gọi là setRiverInformation . Bạn sẽ cập nhật thành phần bằng cách đặt riverInformation khi hàm không đồng bộ được giải quyết. Sau đó quấn getRiverInformation chức năng với useEffect . Đảm bảo chuyển một mảng trống làm đối số thứ hai. Khi lời hứa được giải quyết, hãy cập nhật riverInformation bằng hàm setRiverInformation :

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation() {   const [riverInformation, setRiverInformation] = useState({});    useEffect(() => {    getRiverInformation()    .then(data =>      setRiverInformation(data)    );   }, [])     return(     <div>       <h2>River Information</h2>       <ul>         <li>Continent: {riverInformation.continent}</li>         <li>Length: {riverInformation.length}</li>         <li>Outflow: {riverInformation.outflow}</li>       </ul>     </div>   ) } 

Sau khi chức năng không đồng bộ được giải quyết, hãy cập nhật danh sách không có thứ tự với thông tin mới.

Lưu và đóng file . Khi bạn thực hiện, trình duyệt sẽ làm mới và bạn sẽ tìm thấy dữ liệu sau khi hàm giải quyết:

Cập nhật thông tin sông sau khi tải, 2

Lưu ý thành phần hiển thị trước khi dữ liệu được tải. Ưu điểm của mã không đồng bộ là nó sẽ không chặn kết xuất ban đầu. Trong trường hợp này, bạn có một thành phần hiển thị danh sách mà không có bất kỳ dữ liệu nào, nhưng bạn cũng có thể hiển thị trình giữ chỗ hình tròn hoặc đồ họa vectơ có thể mở rộng (SVG).

Có những lúc bạn chỉ cần tải dữ liệu một lần, chẳng hạn như nếu bạn đang lấy thông tin user hoặc danh sách tài nguyên không bao giờ thay đổi. Nhưng nhiều khi hàm không đồng bộ của bạn sẽ yêu cầu một số đối số. Trong những trường hợp đó, bạn cần phải kích hoạt sử dụng useEffect Hook khi nào dữ liệu thay đổi.

Để mô phỏng điều này, hãy thêm một số dữ liệu khác vào dịch vụ của bạn. Mở rivers.js :

  • nano src/services/rivers.js

Sau đó, thêm một đối tượng có chứa dữ liệu cho một vài con sông nữa. Chọn dữ liệu dựa trên đối số name :

async-tutorial / src / services / rivers.js
const rivers = {  nile: {    continent: 'Africa',    length: '6,650 km',    outflow: 'Mediterranean'  },  amazon: {    continent: 'South America',    length: '6,575 km',    outflow: 'Atlantic Ocean'  },  yangtze: {    continent: 'Asia',    length: '6,300 km',    outflow: 'East China Sea'  },  mississippi: {    continent: 'North America',    length: '6,275 km',    outflow: 'Gulf of Mexico'  } }  export function getRiverInformation(name) {   return new Promise((resolve) => {     setTimeout(() => {       resolve(         rivers[name]       )     }, 1500)   }) } 

Lưu và đóng file . Tiếp theo, mở App.js để bạn có thể thêm các tùy chọn khác:

  • nano src/components/App/App.js

Bên trong App.js , hãy tạo một biến trạng thái và hàm để giữ dòng sông đã chọn bằng useState Hook. Sau đó, thêm một nút cho mỗi sông bằng trình xử lý onClick để cập nhật sông đã chọn. Vượt qua river để RiverInformation sử dụng một prop gọi name :

async-tutorial / src / components / App / App.js
import React, { useState } from 'react'; import './App.css'; import RiverInformation from '../RiverInformation/RiverInformation';  function App() {   const [river, setRiver] = useState('nile');   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <button onClick={() => setRiver('nile')}>Nile</button>       <button onClick={() => setRiver('amazon')}>Amazon</button>       <button onClick={() => setRiver('yangtze')}>Yangtze</button>       <button onClick={() => setRiver('mississippi')}>Mississippi</button>       <RiverInformation name={river} />     </div>   ); }  export default App; 

Lưu và đóng file . Tiếp theo, mở RiverInformation.js :

  • nano src/components/RiverInformation/RiverInformation.js

Lấy name làm chỗ dựa và chuyển nó vào hàm getRiverInformation . Hãy chắc chắn thêm name vào mảng để useEffect , nếu không nó sẽ không chạy lại:

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation({ name }) {   const [riverInformation, setRiverInformation] = useState({});    useEffect(() => {     getRiverInformation(name)     .then(data =>       setRiverInformation(data)     );   }, [name])     return(     <div>       <h2>River Information</h2>       <ul>         <li>Continent: {riverInformation.continent}</li>         <li>Length: {riverInformation.length}</li>         <li>Outflow: {riverInformation.outflow}</li>       </ul>     </div>   ) }  RiverInformation.propTypes = {  name: PropTypes.string.isRequired } 

Trong đoạn mã này, bạn cũng đã thêm một hệ thống gõ yếu với PropTypes , hệ thống này sẽ đảm bảo hệ thống hỗ trợ là một chuỗi.

Lưu các file . Khi bạn làm như vậy, trình duyệt sẽ làm mới và bạn có thể chọn các sông khác nhau. Lưu ý độ trễ giữa khi bạn nhấp vào và khi dữ liệu hiển thị:

Cập nhật thông tin sông, 3

Nếu bạn bỏ sót phần hỗ trợ name khỏi mảng useEffect , bạn sẽ nhận được lỗi xây dựng trong control panel trình duyệt . Nó sẽ như thế này:

Error
Compiled with warnings. ./src/components/RiverInformation/RiverInformation.js Line 13:6: React Hook useEffect has a missing dependency: 'name'. Either include it or remove the dependency array react-hooks/exhaustive-deps Search for the keywords to learn more about each warning. To ignore, add // eslint-disable-next-line to the line before.

Lỗi này cho bạn biết rằng hàm trong hiệu ứng của bạn có các phụ thuộc mà bạn không cài đặt rõ ràng. Trong trường hợp này, rõ ràng là hiệu ứng sẽ không hoạt động, nhưng đôi khi bạn có thể so sánh dữ liệu prop với dữ liệu trạng thái bên trong thành phần, điều này khiến bạn có thể mất dấu các mục trong mảng.

Điều cuối cùng cần làm là thêm một số chương trình phòng thủ vào thành phần của bạn. Đây là một nguyên tắc thiết kế nhấn mạnh tính khả dụng cao cho ứng dụng của bạn. Bạn muốn đảm bảo thành phần của bạn sẽ hiển thị ngay cả khi dữ liệu không ở đúng hình dạng hoặc nếu bạn không nhận được bất kỳ dữ liệu nào từ một yêu cầu API.

Như ứng dụng của bạn hiện tại, hiệu ứng sẽ cập nhật riverInformation với bất kỳ loại dữ liệu nào mà nó nhận được. Đây thường sẽ là một đối tượng, nhưng trong trường hợp không phải, bạn có thể sử dụng chuỗi tùy chọn đảm bảo rằng bạn sẽ không gặp lỗi.

Bên trong RiverInformation.js , thay thế trường hợp chuỗi chuỗi đối tượng bằng chuỗi tùy chọn. Để kiểm tra xem nó có hoạt động hay không, hãy xóa đối tượng mặc định {} khỏi hàm useState :

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation({ name }) {   const [riverInformation, setRiverInformation] = useState();    useEffect(() => {     getRiverInformation(name)     .then(data =>       setRiverInformation(data)     );   }, [name])    return(     <div>       <h2>River Information</h2>       <ul>         <li>Continent: {riverInformation?.continent}</li>         <li>Length: {riverInformation?.length}</li>         <li>Outflow: {riverInformation?.outflow}</li>       </ul>     </div>   ) }  RiverInformation.propTypes = {   name: PropTypes.string.isRequired } 

Lưu và đóng file . Khi bạn làm như vậy, file sẽ vẫn tải mặc dù mã đang tham chiếu đến thuộc tính undefined thay vì đối tượng:

Cập nhật thông tin sông sau khi tải, 4

Lập trình phòng thủ thường được coi là phương pháp hay nhất, nhưng nó đặc biệt quan trọng đối với các hàm không đồng bộ như lệnh gọi API khi bạn không thể đảm bảo phản hồi.

Trong bước này, bạn đã gọi các hàm không đồng bộ trong React. Bạn đã sử dụng useEffect Hook để tìm nạp thông tin mà không cần kích hoạt kết xuất và kích hoạt cập nhật mới bằng cách thêm các điều kiện vào mảng useEffect .

Trong bước tiếp theo, bạn sẽ thực hiện một số thay đổi đối với ứng dụng của bạn để ứng dụng chỉ cập nhật các thành phần khi chúng được mount . Điều này sẽ giúp ứng dụng của bạn tránh bị rò rỉ bộ nhớ.

Bước 2 - Ngăn ngừa lỗi trên các thành phần chưa được mount

Trong bước này, bạn sẽ ngăn cập nhật dữ liệu trên các thành phần chưa được mount . Vì bạn không bao giờ có thể chắc chắn khi nào dữ liệu sẽ giải quyết bằng lập trình không đồng bộ, nên luôn có nguy cơ dữ liệu sẽ giải quyết sau khi thành phần đã bị xóa. Cập nhật dữ liệu trên một thành phần chưa được mount là không hiệu quả và có thể dẫn đến rò rỉ bộ nhớ trong đó ứng dụng của bạn đang sử dụng nhiều bộ nhớ hơn mức cần thiết.

Đến cuối bước này, bạn sẽ biết cách ngăn chặn rò rỉ bộ nhớ bằng cách thêm bảo vệ trong useEffect Hook để chỉ cập nhật dữ liệu khi thành phần được mount .

Thành phần hiện tại sẽ luôn được mount , vì vậy không có khả năng mã sẽ thử và cập nhật thành phần sau khi nó bị xóa khỏi DOM , nhưng hầu hết các thành phần không tin cậy như vậy. Chúng sẽ được thêm và xóa khỏi trang khi user tương tác với ứng dụng. Nếu một thành phần bị xóa khỏi trang trước khi chức năng không đồng bộ giải quyết, bạn có thể bị rò rỉ bộ nhớ.

Để kiểm tra sự cố, hãy cập nhật App.js để có thể thêm và xóa các chi tiết về sông.

Mở App.js :

  • nano src/components/App/App.js

Thêm một nút để chuyển đổi chi tiết sông. Sử dụng useReducer Hook để tạo một hàm để chuyển đổi các chi tiết và một biến để lưu trữ trạng thái được bật tắt:

async-tutorial / src / components / App / App.js
import React, { useReducer, useState } from 'react'; import './App.css'; import RiverInformation from '../RiverInformation/RiverInformation';  function App() {   const [river, setRiver] = useState('nile');   const [show, toggle] = useReducer(state => !state, true);   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <div><button onClick={toggle}>Toggle Details</button></div>       <button onClick={() => setRiver('nile')}>Nile</button>       <button onClick={() => setRiver('amazon')}>Amazon</button>       <button onClick={() => setRiver('yangtze')}>Yangtze</button>       <button onClick={() => setRiver('mississippi')}>Mississippi</button>       {show && <RiverInformation name={river} />}     </div>   ); }  export default App; 

Lưu các file . Khi bạn thực hiện, trình duyệt sẽ reload và bạn có thể chuyển đổi các chi tiết.

Nhấp vào một con sông, sau đó nhấp ngay vào nút Toggle Details để ẩn chi tiết. React sẽ tạo ra một cảnh báo lỗi rằng có khả năng bị rò rỉ bộ nhớ.

Cảnh báo khi thành phần được cập nhật sau khi bị xóa, 5

Để khắc phục sự cố, bạn cần hủy hoặc bỏ qua hàm không đồng bộ bên trong useEffect . Nếu bạn đang sử dụng một thư viện như RxJS , bạn có thể hủy một hành động không đồng bộ khi thành phần ngắt kết nối bằng cách trả về một hàm trong useEffect Hook của bạn. Trong các trường hợp khác, bạn cần một biến để lưu trữ trạng thái được mount .

Mở RiverInformation.js :

  • nano src/components/RiverInformation/RiverInformation.js

Bên trong hàm useEffect , hãy tạo một biến có tên là mounted và đặt nó thành true . Bên trong lệnh gọi lại .then , hãy sử dụng một điều kiện để đặt dữ liệu nếu mounted là đúng:

async-tutorial / src / components / RiverInformation / RiverInformation.js
 import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation({ name }) {   const [riverInformation, setRiverInformation] = useState();    useEffect(() => {     let mounted = true;     getRiverInformation(name)     .then(data => {       if(mounted) {         setRiverInformation(data)       }     });   }, [name])     return(     <div>       <h2>River Information</h2>       <ul>         <li>Continent: {riverInformation?.continent}</li>         <li>Length: {riverInformation?.length}</li>         <li>Outflow: {riverInformation?.outflow}</li>       </ul>     </div>   ) }  RiverInformation.propTypes = {   name: PropTypes.string.isRequired } 

Đến đây bạn đã có biến, bạn cần có thể lật nó khi thành phần ngắt kết nối. Với useEffect Hook, bạn có thể trả về một hàm sẽ chạy khi thành phần ngắt kết nối. Trả về một hàm đặt mounted thành false :

async-tutorial / src / components / RiverInformation / RiverInformation.js
 import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { getRiverInformation } from '../../services/rivers';  export default function RiverInformation({ name }) {   const [riverInformation, setRiverInformation] = useState();    useEffect(() => {     let mounted = true;     getRiverInformation(name)     .then(data => {       if(mounted) {         setRiverInformation(data)       }     });     return () => {      mounted = false;    }   }, [name])    return(     <div>       <h2>River Information</h2>       <ul>         <li>Continent: {riverInformation?.continent}</li>         <li>Length: {riverInformation?.length}</li>         <li>Outflow: {riverInformation?.outflow}</li>       </ul>     </div>   ) }  RiverInformation.propTypes = {   name: PropTypes.string.isRequired } 

Lưu các file . Khi thực hiện, bạn có thể chuyển đổi các chi tiết mà không gặp lỗi.

Không có cảnh báo khi bật tắt, 6

Khi bạn ngắt kết nối, thành phần useEffect cập nhật biến. Hàm không đồng bộ sẽ vẫn giải quyết, nhưng nó sẽ không thực hiện bất kỳ thay đổi nào đối với các thành phần chưa được mount . Điều này sẽ ngăn chặn rò rỉ bộ nhớ.

Trong bước này, bạn chỉ đặt trạng thái cập nhật ứng dụng khi một thành phần được mount . Bạn đã cập nhật useEffect Hook để theo dõi xem thành phần có được mount hay không và trả về một hàm để cập nhật giá trị khi thành phần ngắt kết nối.

Trong bước tiếp theo, bạn sẽ tải các thành phần không đồng bộ để chia mã thành các gói nhỏ hơn mà user sẽ tải khi cần thiết.

Bước 3 - Lười biếng Tải một thành phần với sự Suspenselazy

Trong bước này, bạn sẽ tách mã của bạn bằng React Suspenselazy . Khi các ứng dụng phát triển, kích thước của bản dựng cuối cùng cũng tăng theo. Thay vì buộc user download toàn bộ ứng dụng, bạn có thể chia mã thành các phần nhỏ hơn. React Suspenselazy làm việc với webpack và các hệ thống xây dựng khác để chia mã của bạn thành các phần nhỏ hơn để user có thể tải theo yêu cầu. Trong tương lai, bạn có thể sử dụng Suspense để tải nhiều loại dữ liệu, bao gồm cả các yêu cầu API.

Khi kết thúc bước này, bạn có thể tải các thành phần không đồng bộ, chia các ứng dụng lớn thành các phần nhỏ hơn, tập trung hơn.

Lúc này, bạn chỉ làm việc với việc tải dữ liệu không đồng bộ, nhưng bạn cũng có thể tải các thành phần không đồng bộ. Quá trình này, thường được gọi là tách mã , giúp giảm kích thước các gói mã của bạn để user của bạn không phải download ứng dụng đầy đủ nếu họ chỉ sử dụng một phần của nó.

Thông thường, bạn nhập mã tĩnh, nhưng bạn có thể nhập mã động bằng cách gọi import dưới dạng một hàm thay vì một câu lệnh. Mã sẽ như thế này:

import('my-library') .then(library => library.action()) 

React cung cấp cho bạn một bộ công cụ bổ sung có tên là lazySuspense . React Suspense cuối cùng sẽ mở rộng để xử lý tải dữ liệu , nhưng hiện tại bạn có thể sử dụng nó để tải các thành phần.

Mở App.js :

  • nano src/components/App/App.js

Sau đó nhập lazySuspense từ react :

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react'; import './App.css'; import RiverInformation from '../RiverInformation/RiverInformation';  function App() {   const [river, setRiver] = useState('nile');   const [show, toggle] = useReducer(state => !state, true);   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <div><button onClick={toggle}>Toggle Details</button></div>       <button onClick={() => setRiver('nile')}>Nile</button>       <button onClick={() => setRiver('amazon')}>Amazon</button>       <button onClick={() => setRiver('yangtze')}>Yangtze</button>       <button onClick={() => setRiver('mississippi')}>Mississippi</button>       {show && <RiverInformation name={river} />}     </div>   ); }  export default App; 

lazySuspsense có hai công việc riêng biệt. Bạn sử dụng hàm lazy để nhập động thành phần và đặt nó thành một biến. Suspense là một thành phần tích hợp sẵn mà bạn sử dụng để hiển thị thông báo dự phòng trong khi mã đang tải.

Thay thế import RiverInformation from '../RiverInformation/RiverInformation'; với lời kêu gọi lazy . Gán kết quả cho một biến có tên là RiverInformation . Sau đó, bao bọc {show && <RiverInformation name={river} />} với thành phần Suspense<div> với thông báo Loading Component tới phương tiện fallback :

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react'; import './App.css'; const RiverInformation = lazy(() => import('../RiverInformation/RiverInformation'));  function App() {   const [river, setRiver] = useState('nile');   const [show, toggle] = useReducer(state => !state, true);   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <div><button onClick={toggle}>Toggle Details</button></div>       <button onClick={() => setRiver('nile')}>Nile</button>       <button onClick={() => setRiver('amazon')}>Amazon</button>       <button onClick={() => setRiver('yangtze')}>Yangtze</button>       <button onClick={() => setRiver('mississippi')}>Mississippi</button>       <Suspense fallback={<div>Loading Component</div>}>         {show && <RiverInformation name={river} />}       </Suspense>     </div>   ); }  export default App; 

Lưu các file . Khi bạn làm như vậy, hãy reload trang và bạn sẽ thấy rằng thành phần được tải động. Nếu bạn muốn xem thông báo đang tải, bạn có thể điều chỉnh phản hồi trong trình duyệt web Chrome .

Đang tải thành phần

Nếu chuyển đến tab Mạng trong Chrome hoặc Firefox , bạn sẽ thấy rằng mã được chia thành nhiều phần khác nhau.

Miếng, mảnh nhỏ

Theo mặc định, mỗi đoạn có một số, nhưng với Tạo ứng dụng React kết hợp với webpack, bạn có thể đặt tên cho đoạn bằng cách thêm comment bằng lệnh động.

Trong App.js , thêm comment của /* webpackChunkName: "RiverInformation" */ bên trong hàm import :

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react'; import './App.css'; const RiverInformation = lazy(() => import(/* webpackChunkName: "RiverInformation" */ '../RiverInformation/RiverInformation'));  function App() {   const [river, setRiver] = useState('nile');   const [show, toggle] = useReducer(state => !state, true);   return (     <div className="wrapper">       <h1>World's Longest Rivers</h1>       <div><button onClick={toggle}>Toggle Details</button></div>       <button onClick={() => setRiver('nile')}>Nile</button>       <button onClick={() => setRiver('amazon')}>Amazon</button>       <button onClick={() => setRiver('yangtze')}>Yangtze</button>       <button onClick={() => setRiver('mississippi')}>Mississippi</button>       <Suspense fallback={<div>Loading Component</div>}>         {show && <RiverInformation name={river} />}       </Suspense>     </div>   ); }  export default App; 

Lưu và đóng file . Khi bạn làm như vậy, trình duyệt sẽ làm mới và đoạn RiverInformation sẽ có một tên duy nhất.

Chunk thông tin sông

Trong bước này, bạn đã tải không đồng bộ các thành phần. Bạn đã sử dụng lazySuspense để nhập động các thành phần và hiển thị thông báo đang tải khi thành phần tải. Bạn cũng đã đặt tên tùy chỉnh cho các khối webpack để cải thiện khả năng đọc và gỡ lỗi.

Kết luận

Các chức năng không đồng bộ tạo ra các ứng dụng thân thiện với user hiệu quả. Tuy nhiên, lợi thế của chúng đi kèm với một số chi phí nhỏ có thể phát triển thành lỗi trong chương trình của bạn. Đến đây bạn có các công cụ cho phép bạn chia các ứng dụng lớn thành các phần nhỏ hơn và tải dữ liệu không đồng bộ trong khi vẫn cung cấp cho user một ứng dụng hiển thị. Bạn có thể sử dụng kiến thức để kết hợp các yêu cầu API và thao tác dữ liệu không đồng bộ vào các ứng dụng của bạn , tạo ra trải nghiệm user nhanh chóng và tin cậy .

Nếu bạn muốn đọc thêm các hướng dẫn về React, hãy xem trang Chủ đề React của ta hoặc quay lại trang Cách viết mã trong chuỗi React.js .


Tags:

Các tin liên quan