Phản ứng hồi hộp trong thực tế | Thủ thuật CSS

[ad_1]

Bài đăng này là về cách hiểu Suspense hoạt động, những gì nó làm và xem làm thế nào nó có thể tích hợp vào một ứng dụng web thực sự. Chúng ta sẽ xem xét cách tích hợp định tuyến tải dữ liệu với Hồi hộp trong Phản ứng. Để định tuyến, tôi sẽ sử dụng JavaScript vanilla và tôi sẽ sử dụng thư viện GraphQL phản ứng vi mô của riêng tôi để lấy dữ liệu.

Nếu bạn đang tự hỏi về React Router, nó có vẻ tuyệt vời, nhưng tôi chưa bao giờ có cơ hội sử dụng nó. Dự án phụ của riêng tôi có một câu chuyện định tuyến đủ đơn giản mà tôi luôn luôn làm nó bằng tay. Ngoài ra, sử dụng JavaScript vanilla sẽ cho chúng ta cái nhìn rõ hơn về cách thức hoạt động của Suspense.

Một chút nền tảng

Hãy để từ chối nói về Hồi hộp. Kingsley Silas cung cấp một cái nhìn tổng quan kỹ lưỡng về nó, nhưng điều đầu tiên cần lưu ý là nó vẫn là một API thử nghiệm. Điều đó có nghĩa là – và các tài liệu của React cũng nói như vậy – không dựa vào nó cho công việc sẵn sàng sản xuất. Ở đó, luôn luôn có một cơ hội nó sẽ thay đổi giữa bây giờ và khi nó đầy đủ, vì vậy hãy ghi nhớ điều đó.

Điều đó nói rằng, Suspense là tất cả về việc duy trì giao diện người dùng nhất quán khi đối mặt với các phụ thuộc không đồng bộ, chẳng hạn như các thành phần React được tải một cách lười biếng, dữ liệu GraphQL, v.v. Suspense cung cấp API cấp thấp cho phép bạn dễ dàng duy trì giao diện người dùng của mình trong khi ứng dụng của bạn đang quản lý những thứ này.

Nhưng "nhất quán" nghĩa là gì trong trường hợp này? Điều đó có nghĩa là chứ không phải hiển thị một giao diện người dùng đã hoàn thành một phần. Điều đó có nghĩa là, nếu có ba nguồn dữ liệu trên trang và một trong số chúng đã hoàn thành, chúng tôi không muốn hiển thị đoạn trạng thái được cập nhật đó, với một công cụ quay vòng bên cạnh hai trạng thái đã lỗi thời các mảnh của nhà nước.

Những gì chúng tôi làm muốn làm là cho người dùng biết rằng dữ liệu đang tải, trong khi tiếp tục hiển thị UI cũ hoặc UI thay thế cho biết chúng tôi đang chờ dữ liệu; Hồi hộp cũng hỗ trợ, mà tôi sẽ tham gia.

Chính xác thì Hồi hộp làm gì

Đây là tất cả ít phức tạp hơn nó có vẻ. Theo truyền thống trong React, bạn sẽ đặt trạng thái và UI của bạn sẽ cập nhật. Cuộc sống thật đơn giản. Nhưng nó cũng dẫn đến các loại mâu thuẫn được mô tả ở trên. Những gì Suspense bổ sung là khả năng để một thành phần thông báo React tại thời điểm kết xuất mà nó đang chờ dữ liệu không đồng bộ; điều này được gọi là đình chỉ và nó có thể xảy ra ở bất cứ đâu trong cây của thành phần, bao nhiêu lần nếu cần, cho đến khi cây sẵn sàng. Khi một thành phần tạm ngưng, React sẽ từ chối hiển thị cập nhật trạng thái đang chờ xử lý cho đến khi tất cả các phụ thuộc bị đình chỉ đã được thỏa mãn.

Vậy điều gì xảy ra khi một thành phần đình chỉ? React sẽ tra cứu cây, tìm thành phần đầu tiên và đưa ra dự phòng của nó. Tôi sẽ cung cấp nhiều ví dụ, nhưng bây giờ, hãy biết rằng bạn có thể cung cấp điều này:

  <Dự phòng hồi hộp = {}>  

Quang và thành phần sẽ hiển thị nếu bất kỳ thành phần con nào của bị đình chỉ.

Nhưng điều gì sẽ xảy ra nếu chúng ta đã có một giao diện người dùng phù hợp, hợp lệ và người dùng tải dữ liệu mới, khiến một thành phần bị đình chỉ? Điều này sẽ khiến toàn bộ giao diện người dùng hiện tại không hiển thị và dự phòng hiển thị. Điều đó vẫn nhất quán, nhưng hầu như không phải là một UX tốt. Chúng tôi muốn giao diện người dùng cũ ở lại trên màn hình trong khi dữ liệu mới đang tải.

Để hỗ trợ điều này, React cung cấp API thứ hai, useTransition, giúp thay đổi trạng thái một cách hiệu quả trong bộ nhớ . Nói cách khác, nó cho phép bạn đặt trạng thái trong bộ nhớ trong khi vẫn giữ giao diện người dùng hiện có trên màn hình; React theo nghĩa đen sẽ giữ một bản sao thứ hai của cây thành phần của bạn được hiển thị trong bộ nhớ và đặt trạng thái trên cây . Các thành phần có thể tạm dừng, nhưng chỉ trong bộ nhớ, vì vậy giao diện người dùng hiện tại của bạn sẽ tiếp tục hiển thị trên màn hình. Khi thay đổi trạng thái hoàn tất và tất cả các đình chỉ đã được giải quyết, thay đổi trạng thái trong bộ nhớ sẽ hiển thị trên màn hình. Rõ ràng là bạn muốn cung cấp thông tin phản hồi cho người dùng của mình trong khi điều này đang xảy ra, vì vậy useTransition cung cấp một boolean đang chờ xử lý, bạn có thể sử dụng để hiển thị một số thông báo "đang tải" nội tuyến trong khi bị đình chỉ đang được giải quyết trong bộ nhớ.

Khi bạn nghĩ về nó, có lẽ bạn không muốn giao diện người dùng hiện tại của mình hiển thị vô thời hạn trong khi quá trình tải của bạn đang chờ xử lý. Nếu người dùng cố gắng làm một cái gì đó và một khoảng thời gian dài trôi qua trước khi nó kết thúc, có lẽ bạn nên xem xét giao diện người dùng hiện tại đã lỗi thời và không hợp lệ. Tại thời điểm này, có lẽ bạn sẽ muốn cây thành phần của bạn tạm ngưng và dự phòng của bạn sẽ hiển thị.

Để thực hiện điều này, useTransition cần một giá trị thời gian chờ . Điều này cho biết lượng thời gian bạn sẵn sàng để trạng thái trong bộ nhớ thay đổi chạy trước khi bạn tạm dừng.

  const Thành phần = đạo cụ => {
const [startTransition, isPending] = useTransition ({timeoutMs: 3000});
// .....
};  

Ở đây, startTransition là một chức năng. Khi bạn muốn chạy thay đổi trạng thái "trong bộ nhớ", bạn gọi startTransition và chuyển một biểu thức lambda làm thay đổi trạng thái của bạn.

  startTransition (() => {
công văn ({loại: LOAD_DATA_OR_SOMETHING, giá trị: 42});
})  

Bạn có thể gọi startTransition bất cứ nơi nào bạn muốn. Bạn có thể chuyển nó cho các thành phần con, v.v. Khi bạn gọi nó, mọi thay đổi trạng thái bạn thực hiện sẽ xảy ra trong bộ nhớ. Nếu xảy ra đình chỉ, isPending sẽ trở thành sự thật, bạn có thể sử dụng để hiển thị một số loại chỉ báo tải nội tuyến.

Đó là nó. Đó là những gì Hồi hộp làm.

Phần còn lại của bài đăng này sẽ nhận được một số mã thực tế để tận dụng các tính năng này.

Ví dụ: Điều hướng

Để gắn điều hướng vào Hồi hộp, bạn sẽ rất vui khi biết rằng React cung cấp một nguyên thủy để làm điều này: React.lazy . Đây là một hàm lấy biểu thức lambda trả về Promise, phân giải thành phần React. Kết quả của cuộc gọi chức năng này trở thành thành phần được tải lười biếng của bạn. Nghe có vẻ phức tạp, nhưng có vẻ như thế này:

  const SettingsComponent = lazy (() => import ("./ mô-đun / cài đặt / cài đặt"));  

SettingsComponent hiện là thành phần React, khi được kết xuất (nhưng không phải trước đó), sẽ gọi hàm chúng ta đã truyền vào, sẽ gọi import () và tải mô-đun JavaScript đặt tại ./ mô-đun / cài đặt / cài đặt .

Phần quan trọng là đây: trong khi nhập () đang trong chuyến bay, kết xuất thành phần SettingsComponent sẽ tạm dừng. Dường như chúng ta có tất cả các mảnh trong tay, vì vậy hãy đặt chúng lại với nhau và xây dựng một số điều hướng dựa trên Hồi hộp.

Người trợ giúp điều hướng

Nhưng trước tiên, đối với ngữ cảnh, tôi sẽ trình bày ngắn gọn về cách quản lý trạng thái điều hướng trong ứng dụng này, do đó, mã Hồi hộp sẽ có ý nghĩa hơn.

Tôi sẽ sử dụng ứng dụng danh sách sách của mình. Nó chỉ là một dự án phụ của tôi, tôi chủ yếu giữ xung quanh để làm hỏng công nghệ web tiên tiến. Nó được viết bởi một mình tôi, vì vậy mong đợi các phần của nó sẽ không được tinh chỉnh (đặc biệt là thiết kế).

Ứng dụng này nhỏ, với khoảng tám mô-đun khác nhau mà người dùng có thể duyệt đến mà không cần điều hướng sâu hơn. Bất kỳ trạng thái tìm kiếm nào mà mô-đun có thể sử dụng đều được lưu trữ trong chuỗi truy vấn URL. Với ý nghĩ này, có một vài phương pháp để loại bỏ tên mô-đun hiện tại và trạng thái tìm kiếm từ URL. Mã này sử dụng các gói truy vấn từ npm, và trông giống như thế này (một số chi tiết đã bị xóa vì đơn giản, như xác thực).

  nhập createdHistory từ "history / createdBrowserHistory";
nhập queryString từ "chuỗi truy vấn";
xuất lịch sử const = createdHistory ();
hàm xuất getCienUrlState () {
hãy để location = history.location;
let Parsed = queryString.parse (location.search);
trở về {
tên đường dẫn: location.pathname,
searchState: đã phân tích cú pháp
};
}
hàm xuất getCienModuleFromUrl () {
hãy để location = history.location;
trả về location.pathname.replace (/  // g, "") .toLowerCase ();
}  

Tôi có bộ giảm tốc appSinstall giữ mô-đun hiện tại và searchState cho ứng dụng và sử dụng các phương thức này để đồng bộ hóa với URL khi cần.

Các mảnh của điều hướng dựa trên Hồi hộp

Hãy bắt đầu với một số công việc Hồi hộp. Trước tiên, hãy tạo các thành phần được tải lười biếng cho các mô-đun của chúng tôi.

  const ActivateComponent = lazy (() => import ("./ mô-đun / kích hoạt / kích hoạt"));
const AuthenticicateComponent = lazy (() =>
nhập ("./ mô-đun / xác thực / xác thực")
);
const BooksComponent = lazy (() => import ("./ mô-đun / sách / sách"));
const HomeComponent = lazy (() => import ("./ mô-đun / nhà / nhà"));
const ScanComponent = lazy (() => import ("./ mô-đun / quét / quét"));
const SubjectsComponent = lazy (() => import ("./ mô-đun / môn học / môn học"));
const SettingsComponent = lazy (() => import ("./ mô-đun / cài đặt / cài đặt"));
const AdminComponent = lazy (() => import ("./ mô-đun / quản trị viên / quản trị viên"));  

Bây giờ chúng ta cần một phương pháp chọn đúng thành phần dựa trên mô-đun hiện tại. Nếu chúng ta đang sử dụng Bộ định tuyến React, chúng ta sẽ có một số thành phần . Vì chúng tôi đang thực hiện việc này một cách thủ công, một công tắc sẽ hoạt động.

  xuất const getModuleComponent = moduleToLoad => {
if (moduleToLoad == null) {
trả về null;
}
chuyển đổi (moduleToLoad.toLowerCase ()) {
trường hợp "kích hoạt":
trả về ActivateComponent;
trường hợp "xác thực":
trả về xác thựcComponent;
trường hợp "sách":
trả lại BooksComponent;
trường hợp "nhà":
trả về HomeComponent;
trường hợp "quét":
trả về ScanComponent;
trường hợp "đối tượng":
Trả về môn học;
trường hợp "cài đặt":
trả về Cài đặtComponent;
trường hợp "quản trị":
trả lại AdminComponent;
}

trả về HomeComponent;
};  

Toàn bộ mọi thứ kết hợp lại với nhau

Với tất cả các thiết lập nhàm chán trên đường đi, hãy xem toàn bộ root ứng dụng trông như thế nào. Có rất nhiều mã ở đây, nhưng tôi hứa, tương đối ít trong số những dòng này liên quan đến Hồi hộp, và tôi sẽ trình bày tất cả về nó.

  const Ứng dụng = () => {
const [startTransitionNewModule, isNewModulePending] = useTransition ({
thời gian chờ: 3000
});
const [startTransitionModuleUpdate, moduleUpdatePending] = useTransition ({
thời gian chờ: 3000
});
hãy để appStatePacket = useAppState ();
let [appState, _, dispatch] = appStatePacket;
let Thành phần = getModuleComponent (appState.module);
useEffect (() => {
startTransitionNewModule (() => {
công văn ({loại: URL_SYNC});
});
}, []);
useEffect (() => {
trả về lịch sử.listen (vị trí => {
if (appState.module! = getCienModuleFromUrl ()) {
startTransitionNewModule (() => {
công văn ({loại: URL_SYNC});
});
} khác {
startTransitionModuleUpdate (() => {
công văn ({loại: URL_SYNC});
});
}
});
}, [appState.module]);
trở về (


{isNewModulePending? : null} <Dự phòng hồi hộp = {}>
{Thành phần? : null}
); };

Đầu tiên, chúng tôi có hai cách gọi khác nhau useTransition . Chúng tôi sẽ sử dụng một để định tuyến đến một mô-đun mới và cái còn lại để cập nhật trạng thái tìm kiếm cho mô-đun hiện tại. Tại sao lại có sự khác biệt? Chà, khi trạng thái tìm kiếm của mô-đun đang cập nhật, mô-đun đó có thể sẽ muốn hiển thị một chỉ báo tải nội tuyến. Trạng thái cập nhật đó được giữ bởi biến [module902020] moduleUpdatePending mà bạn sẽ thấy tôi đặt bối cảnh cho mô-đun hoạt động để lấy và sử dụng khi cần:

  
{isNewModulePending? : null} <Dự phòng hồi hộp = {}>
{Thành phần? : null} // tô sáng

appStatePacket là kết quả của trình giảm trạng thái ứng dụng mà tôi đã thảo luận ở trên (nhưng không hiển thị). Nó chứa các phần khác nhau của trạng thái ứng dụng hiếm khi thay đổi (chủ đề màu, trạng thái ngoại tuyến, mô-đun hiện tại, v.v.).

  hãy để appStatePacket = useAppState ();  

Một lát sau, tôi lấy bất kỳ thành phần nào hoạt động, dựa trên tên mô-đun hiện tại. Ban đầu điều này sẽ là null.

  hãy để Thành phần = getModuleComponent (appState.module);  

Cuộc gọi đầu tiên tới useEffect sẽ cho trình giảm tốc appSinstall của chúng tôi đồng bộ hóa với URL khi khởi động.

  useEffect (() => {
startTransitionNewModule (() => {
công văn ({loại: URL_SYNC});
});
}, []);  

Vì đây là mô-đun ban đầu mà ứng dụng web điều hướng đến, tôi gói nó trong startTransitionNewModule để chỉ ra rằng một mô-đun mới đang tải. Mặc dù có thể có bộ giảm tốc appSinstall có tên mô-đun ban đầu là trạng thái ban đầu, nhưng điều này ngăn chúng ta gọi lại cuộc gọi bắt đầu startTransitionNewModule có nghĩa là ranh giới Hồi hộp của chúng ta sẽ hiển thị dự phòng ngay lập tức, thay vì sau khi hết thời gian.

Cuộc gọi tiếp theo đến useEffect thiết lập đăng ký lịch sử. Không có vấn đề gì, khi url thay đổi, chúng tôi sẽ nói với cài đặt ứng dụng của mình để đồng bộ hóa với URL. Sự khác biệt duy nhất là startTransition cùng một cuộc gọi được gói gọn.

  useEffect (() => {
trả về lịch sử.listen (vị trí => {
if (appState.module! = getCienModuleFromUrl ()) {
startTransitionNewModule (() => {
công văn ({loại: URL_SYNC});
});
} khác {
startTransitionModuleUpdate (() => {
công văn ({loại: URL_SYNC});
});
}
});
}, [appState.module]);  

Nếu chúng tôi duyệt qua một mô-đun mới, chúng tôi gọi startTransitionNewModule . Nếu chúng tôi đang tải một thành phần chưa được tải, React.lazy sẽ tạm dừng và chỉ báo đang chờ xử lý chỉ hiển thị cho thư mục gốc của ứng dụng sẽ hiển thị một công cụ tải spinner ở đầu ứng dụng trong khi thành phần lười biếng được tải và tải. Do cách useTransition hoạt động, màn hình hiện tại sẽ tiếp tục hiển thị trong ba giây. Nếu thời gian đó hết hạn và thành phần vẫn chưa sẵn sàng, giao diện người dùng của chúng tôi sẽ tạm dừng và dự phòng sẽ hiển thị, sẽ hiển thị thành phần :

  {isNewModulePending? : null}
<Dự phòng hồi hộp = {}>
{Thành phần? : null}

Nếu chúng tôi không thay đổi các mô-đun, chúng tôi gọi startTransitionModuleUpdate :

  startTransitionModuleUpdate (() => {
công văn ({loại: URL_SYNC});
});  

Nếu bản cập nhật gây ra đình chỉ, chỉ báo đang chờ xử lý chúng tôi đặt vào ngữ cảnh sẽ được kích hoạt. Thành phần hoạt động có thể phát hiện điều đó và hiển thị bất kỳ chỉ số tải nội tuyến nào nó muốn. Như trước đây, nếu hệ thống treo mất nhiều hơn ba giây, cùng một ranh giới Hồi hộp từ trước sẽ được kích hoạt ... trừ khi, như chúng ta sẽ thấy sau đó, có một ranh giới Hồi hộp thấp hơn trong cây.

Một điều quan trọng cần lưu ý là thời gian chờ ba giây này không chỉ áp dụng cho việc tải thành phần, mà còn sẵn sàng để hiển thị. Nếu thành phần tải trong hai giây và khi kết xuất trong bộ nhớ (vì chúng tôi đang ở trong lệnh gọi startTransition ), thì useTransition sẽ tiếp tục chờ thêm một giây nữa trước khi tạm dừng.

Khi viết bài đăng trên blog này, tôi đã sử dụng các chế độ mạng chậm của Chrome để giúp tải chậm, để kiểm tra ranh giới Hồi hộp của tôi. Các cài đặt nằm trong tab Mạng của các công cụ phát triển của Chrome.

Hãy mở ứng dụng của chúng tôi đến mô-đun cài đặt. Điều này sẽ được gọi là:

  công văn ({loại: URL_SYNC});  

Trình giảm tốc của chúng tôi Cài đặt sẽ đồng bộ hóa với URL, sau đó đặt mô-đun thành "cài đặt". Điều này sẽ xảy ra bên trong startTransitionNewModule để khi thành phần được tải lười biếng cố gắng kết xuất, nó sẽ tạm dừng. Vì chúng tôi đang ở trong startTransitionNewModule isNewModulePending sẽ chuyển sang true ]

Nếu thành phần vẫn chưa sẵn sàng hiển thị trong vòng ba giây, phiên bản trong bộ nhớ của cây thành phần của chúng tôi sẽ chuyển qua, tạm dừng và ranh giới Hồi hộp của chúng tôi sẽ kết xuất thành phần .
Khi thực hiện xong, mô-đun cài đặt sẽ hiển thị.

Vậy điều gì xảy ra khi chúng ta duyệt một nơi mới? Về cơ bản giống như trước đây, ngoại trừ cuộc gọi này:

  công văn ({loại: URL_SYNC});  

Quang sẽ đến từ ví dụ thứ hai của useEffect . Hãy duyệt qua mô-đun sách và xem điều gì sẽ xảy ra. Đầu tiên, spinner nội tuyến hiển thị như mong đợi:

Nếu hết thời gian ba giây, ranh giới Hồi hộp của chúng tôi sẽ hiển thị dự phòng:
Và cuối cùng, mô-đun sách của chúng tôi tải:

Tìm kiếm và cập nhật

Hãy ở lại trong mô-đun sách và cập nhật chuỗi tìm kiếm URL để khởi động một tìm kiếm mới. Nhớ lại từ trước rằng chúng tôi đã phát hiện cùng một mô-đun trong lần gọi thứ hai useEffect và sử dụng một cuộc gọi useTransition dành riêng cho nó. Từ đó, chúng tôi đã đưa chỉ báo đang chờ xử lý vào ngữ cảnh cho bất kỳ mô-đun nào đang hoạt động để chúng tôi lấy và sử dụng.

Chúng ta hãy xem một số mã để thực sự sử dụng nó. Không có nhiều mã liên quan đến Hồi hộp ở đây. Tôi đã lấy giá trị từ ngữ cảnh và nếu đúng, hiển thị một công cụ quay vòng nội tuyến trên kết quả hiện tại của tôi. Hãy nhớ lại rằng điều này xảy ra khi một cuộc gọi useTransition đã bắt đầu và ứng dụng bị treo trong bộ nhớ . Trong khi điều đó xảy ra, chúng tôi tiếp tục hiển thị giao diện người dùng hiện có, nhưng với chỉ số tải này.

  const BookResults: SFC <{ books: any; uiView: any }> = ({sách, uiView}) => {
  const isUpdating = useContext (ModuleUpdateContext);
  trở về (
    <>
      {! sách.length? (
        
          Không tìm thấy sách         
      ) : vô giá trị}       {Đang cập nhật? : null}       {uiView.isGridView? (                ): uiView.isBasicList? (                ): uiView.isCoversList? (                ) : vô giá trị}        ); };

Hãy đặt một thuật ngữ tìm kiếm và xem điều gì sẽ xảy ra. Đầu tiên, spinner nội tuyến hiển thị.

Sau đó, nếu hết thời gian useTransition chúng tôi sẽ nhận được dự phòng của ranh giới Hồi hộp. Mô-đun sách xác định ranh giới Hồi hộp của chính nó để cung cấp chỉ báo tải được điều chỉnh tốt hơn, trông giống như sau:

Đây là một điểm quan trọng. Khi thực hiện dự phòng ranh giới Hồi hộp, cố gắng không đưa ra bất kỳ loại tin nhắn spinner và "tải" nào. Điều đó có ý nghĩa đối với điều hướng cấp cao nhất của chúng tôi bởi vì không có nhiều việc phải làm. Nhưng khi bạn ở trong một phần cụ thể của ứng dụng, hãy cố gắng làm cho dự phòng của bạn sử dụng lại nhiều thành phần tương tự với một số chỉ báo tải trong đó dữ liệu sẽ có - nhưng với mọi thứ khác bị vô hiệu hóa.

Đây là những gì các thành phần có liên quan trông giống như mô-đun sách của tôi:

  const RenderModule: SFC <{}> = ({}) => {
  const uiView = useBookSearchUiView ();
  const [lastBookResults, setLastBookResults] = useState ({
    tổng số trang: 0,
    kết quả đếm: 0
  });
  trở về (
    
      <Dự phòng hồi hộp = {}>                     
  ); }; const Dự phòng: SFC <{ uiView: BookSearchUiView; totalPages: number; resultsCount: number; }> = ({uiView, TotalPages, resultsCount}) => {   trở về (     <>              {uiView.isGridView? (                ): (         

          Sách đang tải         

      )}        ); };

Một lưu ý nhanh về tính nhất quán

Trước khi chúng tôi tiếp tục, tôi muốn chỉ ra một điều từ các ảnh chụp màn hình trước đó. Nhìn vào công cụ quay vòng nội tuyến hiển thị trong khi tìm kiếm đang chờ xử lý, sau đó nhìn vào màn hình khi tìm kiếm đó bị treo và tiếp theo, kết quả đã hoàn thành:

Lưu ý cách có nhãn "C ++" ở bên phải của ngăn tìm kiếm, với tùy chọn xóa nhãn khỏi truy vấn tìm kiếm? Hay đúng hơn, chú ý làm thế nào nhãn đó chỉ có trên hai ảnh chụp màn hình thứ hai? Thời điểm URL cập nhật, trạng thái ứng dụng điều chỉnh nhãn đó được cập nhật; tuy nhiên, trạng thái đó ban đầu không hiển thị. Ban đầu, bản cập nhật trạng thái tạm dừng trong bộ nhớ (vì chúng tôi đã sử dụng useTransition) và giao diện người dùng trước tiếp tục hiển thị.

Sau đó, dự phòng trở lại. Dự phòng kết xuất phiên bản bị vô hiệu hóa của cùng một thanh tìm kiếm, hiển thị trạng thái tìm kiếm hiện tại (theo lựa chọn). Bây giờ chúng tôi đã xóa giao diện người dùng trước đó của chúng tôi (kể từ bây giờ, nó khá cũ và cũ) và đang chờ tìm kiếm được hiển thị trên thanh menu bị vô hiệu hóa.

Đây là loại Hồi hộp nhất quán cung cấp cho bạn, miễn phí.

Bạn có thể dành thời gian để tạo ra các trạng thái ứng dụng đẹp và React thực hiện công việc của việc phỏng đoán xem mọi thứ đã sẵn sàng hay chưa, mà bạn không cần phải thực hiện các lời hứa.

Ranh giới hồi hộp lồng nhau

Chúng ta hãy giả sử điều hướng cấp cao nhất của chúng tôi mất một thời gian để tải thành phần sách của chúng tôi đến mức mà chúng tôi vẫn đang tải, xin lỗi spinner từ ranh giới Hồi hộp. Từ đó, tải thành phần sách và ranh giới Hồi hộp mới bên trong thành phần sách được hiển thị. Nhưng, sau đó, khi kết xuất tiếp tục, truy vấn tìm kiếm sách của chúng tôi kích hoạt và tạm dừng. Chuyện gì sẽ xảy ra? Ranh giới Hồi hộp cấp cao nhất sẽ tiếp tục hiển thị, cho đến khi mọi thứ sẵn sàng, hoặc ranh giới Hồi hộp thấp hơn trong sách sẽ tiếp quản?

Câu trả lời là câu trả lời sau. Khi các ranh giới Hồi hộp mới xuất hiện thấp hơn trên cây, dự phòng của chúng sẽ thay thế dự phòng của bất kỳ dự phòng Hồi hộp nghi ngờ nào trước đây đã được hiển thị. Hiện tại có một API không ổn định để ghi đè lên điều này, nhưng nếu bạn đang làm tốt công việc tạo ra các dự phòng của mình, đây có thể là hành vi bạn muốn. Bạn không muốn vẫn tải, xin lỗi, hãy tiếp tục hiển thị. Thay vào đó, ngay khi thành phần sách sẵn sàng, bạn hoàn toàn muốn hiển thị lớp vỏ đó với thông điệp chờ được nhắm mục tiêu hơn.

Bây giờ, điều gì sẽ xảy ra nếu mô-đun sách của chúng tôi tải và bắt đầu hiển thị trong khi trình khởi động startTransition vẫn hiển thị và sau đó tạm dừng? Nói cách khác, hãy tưởng tượng rằng startTransition của chúng tôi có thời gian chờ là ba giây, thành phần sách hiển thị, ranh giới Hồi hộp lồng nhau nằm trong cây thành phần sau một giây và truy vấn tìm kiếm tạm dừng. Hai giây còn lại sẽ trôi qua trước khi ranh giới Hồi hộp lồng nhau mới kết xuất lại dự phòng, hay dự phòng sẽ hiển thị ngay lập tức? Câu trả lời, có lẽ đáng ngạc nhiên, là dự phòng Suspense mới sẽ hiển thị ngay lập tức theo mặc định. Điều đó bởi vì tốt nhất là hiển thị một giao diện người dùng mới, hợp lệ càng nhanh càng tốt, vì vậy người dùng có thể thấy rằng mọi thứ đang diễn ra và đang tiến triển.

Làm thế nào dữ liệu phù hợp trong

Điều hướng là tốt, nhưng làm thế nào để tải dữ liệu phù hợp với tất cả những điều này?

Nó phù hợp hoàn toàn và minh bạch. Tải dữ liệu kích hoạt các hệ thống treo giống như điều hướng với React.lazy và nó nối vào tất cả cùng useTransition và ranh giới Hồi hộp. Đây là điều đáng kinh ngạc về Hồi hộp: tất cả các phụ thuộc không đồng bộ của bạn hoạt động trơn tru trong cùng hệ thống này. Quản lý các yêu cầu không đồng bộ khác nhau này theo cách thủ công để đảm bảo tính nhất quán là một cơn ác mộng trước Hồi hộp, đó chính là lý do tại sao không ai thực hiện. Các ứng dụng web nổi tiếng với các spinners xếp tầng dừng lại ở thời điểm không thể đoán trước, tạo ra các UI không nhất quán chỉ mới hoàn thành một phần.

OK, nhưng làm thế nào để chúng ta thực sự buộc tải dữ liệu vào đây? Tải dữ liệu trong Suspense là nghịch lý vừa phức tạp hơn, vừa đơn giản.

Tôi sẽ giải thích.

Nếu bạn đang chờ dữ liệu, bạn sẽ đưa ra một lời hứa trong thành phần đọc (hoặc cố đọc) dữ liệu. Lời hứa nên nhất quán dựa trên yêu cầu dữ liệu. Vì vậy, bốn yêu cầu lặp lại cho cùng một truy vấn tìm kiếm "C ++" sẽ đưa ra cùng một lời hứa giống hệt nhau. Điều này ngụ ý một số loại bộ nhớ đệm để quản lý tất cả điều này. Bạn có thể sẽ không tự viết điều này. Thay vào đó, bạn sẽ chỉ hy vọng và chờ thư viện dữ liệu bạn sử dụng để tự cập nhật để hỗ trợ Hồi hộp.

Điều này đã được thực hiện trong thư viện phản ứng micro-graphql của tôi. Thay vì sử dụng hook useQuery bạn sẽ sử dụng hook useSuspenseQuery có API giống hệt nhau, nhưng đưa ra một lời hứa nhất quán khi bạn chờ dữ liệu.

Đợi đã, còn tải trước thì sao ?!

Bộ não của bạn đã chuyển sang đọc những thứ khác trên Hồi hộp nói về thác nước, tìm nạp, tải trước, v.v.? Đừng lo lắng về nó. Đây là tất cả những gì nó có nghĩa.

Giả sử bạn lười tải thành phần sách, kết xuất lại và sau đó yêu cầu một số dữ liệu, gây ra Hồi hộp mới. Yêu cầu mạng đối với thành phần và yêu cầu mạng đối với dữ liệu sẽ xảy ra sau khi một nhóm khác theo kiểu thác nước.

Nhưng đây là phần quan trọng: trạng thái ứng dụng dẫn đến bất kỳ truy vấn ban đầu nào chạy khi thành phần được tải đã có sẵn khi bạn bắt đầu tải thành phần (trong trường hợp này là URL). Vậy tại sao không "bắt đầu" truy vấn ngay khi bạn biết bạn sẽ cần nó? Ngay khi bạn duyệt đến / sách tại sao không tắt truy vấn tìm kiếm hiện tại ngay lúc đó và ở đó, vì vậy nó đã sẵn sàng khi tải thành phần.

Mô-đun phản ứng micro-graphql thực sự có phương pháp tải trước và tôi khuyên bạn nên sử dụng nó. Tải trước dữ liệu là một tối ưu hóa hiệu suất tốt, nhưng nó không liên quan gì đến Suspense. Các ứng dụng React cổ điển có thể (và nên) tải trước dữ liệu ngay khi họ biết họ sẽ cần nó. Các ứng dụng Vue nên tải trước dữ liệu ngay khi họ biết họ sẽ cần nó. Các ứng dụng mảnh dẻ sẽ ... bạn nhận được điểm.

Tải trước dữ liệu là trực giao với Hồi hộp, đây là điều bạn có thể làm với bất kỳ khuôn khổ nào. Nó cũng là thứ mà tất cả chúng ta nên làm, mặc dù không có ai khác.

Nhưng nghiêm túc, làm thế nào để bạn tải trước?

Điều đó tùy thuộc vào bạn. Ít nhất, logic để chạy tìm kiếm hiện tại hoàn toàn cần phải được tách biệt hoàn toàn thành mô-đun độc lập của riêng nó. Theo nghĩa đen, bạn nên chắc chắn rằng chức năng tải trước này nằm trong một tệp. Đừng dựa vào webpack để treeshake; bạn có thể sẽ phải đối mặt với nỗi buồn trong lần tới khi bạn kiểm toán các gói của mình.

Bạn có một phương thức preload () trong gói riêng của mình, vì vậy hãy gọi nó. Gọi nó khi bạn biết bạn sẽ điều hướng đến mô-đun đó. Tôi giả sử React Router có một số loại API để chạy mã khi thay đổi điều hướng. Đối với mã định tuyến vanilla ở trên, tôi gọi phương thức trong công tắc định tuyến đó từ trước. Tôi đã bỏ qua nó để cho ngắn gọn, nhưng mục sách thực sự trông như thế này:

Công tắc

  (moduleToLoad.toLowerCase ()) {
  trường hợp "kích hoạt":
    trả về ActivateComponent;
  trường hợp "xác thực":
    trả về xác thựcComponent;
  trường hợp "sách":
    // tải trước !!!
    sáchPreload ();
    trả lại SáchComponent;  

Đó là nó. Đây là bản demo trực tiếp để chơi xung quanh:

Để sửa đổi giá trị hết thời gian chờ, mặc định là 3000ms, điều hướng đến Cài đặt và kiểm tra tab linh tinh. Chỉ cần chắc chắn để làm mới trang sau khi sửa đổi nó.

Kết thúc

Tôi hiếm khi hào hứng với bất cứ điều gì trong hệ sinh thái nhà phát triển web như tôi đối với Hồi hộp. Đây là một hệ thống cực kỳ tham vọng để quản lý một trong những vấn đề khó khăn nhất trong phát triển web: không đồng bộ.

[ad_2]
Source link: webdesignernews

Leave a Reply

Your email address will not be published. Required fields are marked *