<Suspense> cho phép bạn hiển thị một fallback cho đến khi các thành phần con của nó đã tải xong.

<Suspense fallback={<Loading />}>
<SomeComponent />
</Suspense>

Tham khảo

<Suspense>

Props

  • children: Giao diện người dùng thực tế mà bạn định hiển thị. Nếu children tạm ngưng trong khi hiển thị, ranh giới Suspense sẽ chuyển sang hiển thị fallback.
  • fallback: Một giao diện người dùng thay thế để hiển thị thay cho giao diện người dùng thực tế nếu nó chưa tải xong. Bất kỳ nút React hợp lệ nào đều được chấp nhận, mặc dù trên thực tế, fallback là một chế độ xem giữ chỗ nhẹ, chẳng hạn như trình quay tải hoặc bộ xương. Suspense sẽ tự động chuyển sang fallback khi children tạm ngưng và quay lại children khi dữ liệu đã sẵn sàng. Nếu fallback tạm ngưng trong khi hiển thị, nó sẽ kích hoạt ranh giới Suspense cha gần nhất.

Lưu ý

  • React không giữ lại bất kỳ trạng thái nào cho các lần hiển thị bị tạm ngưng trước khi chúng có thể gắn kết lần đầu tiên. Khi thành phần đã tải, React sẽ thử lại hiển thị cây bị tạm ngưng từ đầu.
  • Nếu Suspense đang hiển thị nội dung cho cây, nhưng sau đó nó lại bị tạm ngưng, thì fallback sẽ được hiển thị lại trừ khi bản cập nhật gây ra nó được gây ra bởi startTransition hoặc useDeferredValue.
  • Nếu React cần ẩn nội dung đã hiển thị vì nó bị tạm ngưng lại, nó sẽ dọn dẹp layout Effects trong cây nội dung. Khi nội dung đã sẵn sàng để hiển thị lại, React sẽ kích hoạt lại layout Effects. Điều này đảm bảo rằng Effects đo bố cục DOM không cố gắng thực hiện điều này trong khi nội dung bị ẩn.
  • React bao gồm các tối ưu hóa ẩn bên dưới như Kết xuất máy chủ phát trực tuyếnHydrat hóa có chọn lọc được tích hợp với Suspense. Đọc tổng quan về kiến trúc và xem bài nói chuyện kỹ thuật để tìm hiểu thêm.

Cách sử dụng

Hiển thị fallback trong khi nội dung đang tải

Bạn có thể bọc bất kỳ phần nào của ứng dụng của bạn bằng một ranh giới Suspense:

<Suspense fallback={<Loading />}>
<Albums />
</Suspense>

React sẽ hiển thị fallback tải của bạn cho đến khi tất cả code và dữ liệu cần thiết bởi các thành phần con đã được tải xong.

Trong ví dụ dưới đây, thành phần Albums tạm ngưng trong khi tìm nạp danh sách album. Cho đến khi nó sẵn sàng hiển thị, React chuyển ranh giới Suspense gần nhất bên trên để hiển thị fallback — thành phần Loading của bạn. Sau đó, khi dữ liệu được tải, React ẩn fallback Loading và hiển thị thành phần Albums với dữ liệu.

import { Suspense } from 'react';
import Albums from './Albums.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<Loading />}>
        <Albums artistId={artist.id} />
      </Suspense>
    </>
  );
}

function Loading() {
  return <h2>🌀 Loading...</h2>;
}

Note

Chỉ các nguồn dữ liệu hỗ trợ Suspense mới kích hoạt thành phần Suspense. Chúng bao gồm:

  • Tìm nạp dữ liệu với các framework hỗ trợ Suspense như RelayNext.js
  • Tải code component một cách lazy với lazy
  • Đọc giá trị của một Promise đã được cache với use

Suspense không phát hiện khi dữ liệu được tìm nạp bên trong một Effect hoặc trình xử lý sự kiện.

Cách chính xác để bạn tải dữ liệu trong component Albums ở trên phụ thuộc vào framework của bạn. Nếu bạn sử dụng một framework hỗ trợ Suspense, bạn sẽ tìm thấy chi tiết trong tài liệu tìm nạp dữ liệu của nó.

Việc tìm nạp dữ liệu hỗ trợ Suspense mà không sử dụng framework theo ý kiến riêng vẫn chưa được hỗ trợ. Các yêu cầu để triển khai một nguồn dữ liệu hỗ trợ Suspense là không ổn định và không được ghi lại. Một API chính thức để tích hợp các nguồn dữ liệu với Suspense sẽ được phát hành trong một phiên bản React trong tương lai.


Tiết lộ nội dung cùng nhau đồng thời

Theo mặc định, toàn bộ cây bên trong Suspense được coi là một đơn vị duy nhất. Ví dụ: ngay cả khi chỉ một trong số các component này tạm ngưng để chờ một số dữ liệu, thì tất cả chúng cùng nhau sẽ được thay thế bằng chỉ báo tải:

<Suspense fallback={<Loading />}>
<Biography />
<Panel>
<Albums />
</Panel>
</Suspense>

Sau đó, sau khi tất cả chúng đã sẵn sàng để hiển thị, chúng sẽ xuất hiện cùng nhau ngay lập tức.

Trong ví dụ dưới đây, cả BiographyAlbums đều tìm nạp một số dữ liệu. Tuy nhiên, vì chúng được nhóm dưới một ranh giới Suspense duy nhất, các thành phần này luôn “hiện ra” cùng nhau đồng thời.

import { Suspense } from 'react';
import Albums from './Albums.js';
import Biography from './Biography.js';
import Panel from './Panel.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<Loading />}>
        <Biography artistId={artist.id} />
        <Panel>
          <Albums artistId={artist.id} />
        </Panel>
      </Suspense>
    </>
  );
}

function Loading() {
  return <h2>🌀 Loading...</h2>;
}

Các component tải dữ liệu không cần phải là con trực tiếp của ranh giới Suspense. Ví dụ: bạn có thể di chuyển BiographyAlbums vào một component Details mới. Điều này không thay đổi hành vi. BiographyAlbums dùng chung ranh giới Suspense cha gần nhất, vì vậy việc hiển thị của chúng được phối hợp cùng nhau.

<Suspense fallback={<Loading />}>
<Details artistId={artist.id} />
</Suspense>

function Details({ artistId }) {
return (
<>
<Biography artistId={artistId} />
<Panel>
<Albums artistId={artistId} />
</Panel>
</>
);
}
<Suspense fallback={<Loading />}>
<Details artistId={artist.id} />
</Suspense>

function Details({ artistId }) {
return (
<>
<Biography artistId={artistId} />
<Panel>
<Albums artistId={artistId} />
</Panel>
</>
);
}

Tiết lộ nội dung lồng nhau khi nó tải

Khi một thành phần tạm ngưng, thành phần Suspense cha gần nhất sẽ hiển thị fallback. Điều này cho phép bạn lồng nhiều thành phần Suspense để tạo ra một chuỗi tải. Fallback của mỗi ranh giới Suspense sẽ được điền vào khi cấp nội dung tiếp theo có sẵn. Ví dụ: bạn có thể cung cấp cho danh sách album fallback riêng:

<Suspense fallback={<BigSpinner />}>
<Biography />
<Suspense fallback={<AlbumsGlimmer />}>
<Panel>
<Albums />
</Panel>
</Suspense>
</Suspense>

Với thay đổi này, việc hiển thị Biography không cần phải “chờ” Albums tải.

Trình tự sẽ là:

  1. Nếu Biography chưa tải xong, BigSpinner sẽ được hiển thị thay cho toàn bộ vùng nội dung.
  2. Khi Biography tải xong, BigSpinner được thay thế bằng nội dung.
  3. Nếu Albums chưa tải xong, AlbumsGlimmer sẽ được hiển thị thay cho AlbumsPanel cha của nó.
  4. Cuối cùng, khi Albums tải xong, nó sẽ thay thế AlbumsGlimmer.
import { Suspense } from 'react';
import Albums from './Albums.js';
import Biography from './Biography.js';
import Panel from './Panel.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<BigSpinner />}>
        <Biography artistId={artist.id} />
        <Suspense fallback={<AlbumsGlimmer />}>
          <Panel>
            <Albums artistId={artist.id} />
          </Panel>
        </Suspense>
      </Suspense>
    </>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}

function AlbumsGlimmer() {
  return (
    <div className="glimmer-panel">
      <div className="glimmer-line" />
      <div className="glimmer-line" />
      <div className="glimmer-line" />
    </div>
  );
}

Các ranh giới Suspense cho phép bạn điều phối những phần nào của giao diện người dùng của bạn sẽ luôn “hiển thị” cùng nhau đồng thời và những phần nào sẽ dần dần tiết lộ thêm nội dung theo một chuỗi các trạng thái tải. Bạn có thể thêm, di chuyển hoặc xóa các ranh giới Suspense ở bất kỳ đâu trong cây mà không ảnh hưởng đến hành vi của phần còn lại của ứng dụng của bạn.

Đừng đặt một ranh giới Suspense xung quanh mọi thành phần. Các ranh giới Suspense không nên chi tiết hơn trình tự tải mà bạn muốn người dùng trải nghiệm. Nếu bạn làm việc với một nhà thiết kế, hãy hỏi họ nơi đặt các trạng thái tải—có khả năng là họ đã đưa chúng vào wireframe thiết kế của họ.

<Suspense fallback={<BigSpinner />}>
<Biography />
<Suspense fallback={<AlbumsGlimmer />}>
<Panel>
<Albums />
</Panel>
</Suspense>
</Suspense>

Với thay đổi này, việc hiển thị Biography không cần phải “chờ” Albums tải.

Trình tự sẽ là:

  1. Nếu Biography chưa tải xong, BigSpinner sẽ được hiển thị thay cho toàn bộ vùng nội dung.
  2. Khi Biography tải xong, BigSpinner được thay thế bằng nội dung.
  3. Nếu Albums chưa tải xong, AlbumsGlimmer sẽ được hiển thị thay cho AlbumsPanel cha của nó.
  4. Cuối cùng, khi Albums tải xong, nó sẽ thay thế AlbumsGlimmer.
import { Suspense } from 'react';
import Albums from './Albums.js';
import Biography from './Biography.js';
import Panel from './Panel.js';

export default function ArtistPage({ artist }) {
  return (
    <>
      <h1>{artist.name}</h1>
      <Suspense fallback={<BigSpinner />}>
        <Biography artistId={artist.id} />
        <Suspense fallback={<AlbumsGlimmer />}>
          <Panel>
            <Albums artistId={artist.id} />
          </Panel>
        </Suspense>
      </Suspense>
    </>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}

function AlbumsGlimmer() {
  return (
    <div className="glimmer-panel">
      <div className="glimmer-line" />
      <div className="glimmer-line" />
      <div className="glimmer-line" />
    </div>
  );
}

Các ranh giới Suspense cho phép bạn điều phối những phần nào của giao diện người dùng của bạn sẽ luôn “hiển thị” cùng nhau đồng thời và những phần nào sẽ dần dần tiết lộ thêm nội dung theo một chuỗi các trạng thái tải. Bạn có thể thêm, di chuyển hoặc xóa các ranh giới Suspense ở bất kỳ đâu trong cây mà không ảnh hưởng đến hành vi của phần còn lại của ứng dụng của bạn.

Đừng đặt một ranh giới Suspense xung quanh mọi thành phần. Các ranh giới Suspense không nên chi tiết hơn trình tự tải mà bạn muốn người dùng trải nghiệm. Nếu bạn làm việc với một nhà thiết kế, hãy hỏi họ nơi đặt các trạng thái tải—có khả năng là họ đã đưa chúng vào wireframe thiết kế của họ.


Hiển thị nội dung cũ trong khi nội dung mới đang tải

Trong ví dụ này, thành phần SearchResults tạm ngưng trong khi tìm nạp kết quả tìm kiếm. Nhập "a", đợi kết quả và sau đó chỉnh sửa thành "ab". Các kết quả cho "a" sẽ được thay thế bằng fallback tải.

import { Suspense, useState } from 'react';
import SearchResults from './SearchResults.js';

export default function App() {
  const [query, setQuery] = useState('');
  return (
    <>
      <label>
        Search albums:
        <input value={query} onChange={e => setQuery(e.target.value)} />
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <SearchResults query={query} />
      </Suspense>
    </>
  );
}

Một mẫu giao diện người dùng thay thế phổ biến là hoãn lại việc cập nhật danh sách và tiếp tục hiển thị các kết quả trước đó cho đến khi các kết quả mới sẵn sàng. Hook useDeferredValue cho phép bạn chuyển một phiên bản hoãn lại của truy vấn xuống:

export default function App() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<label>
Search albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>Loading...</h2>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}

query sẽ cập nhật ngay lập tức, vì vậy đầu vào sẽ hiển thị giá trị mới. Tuy nhiên, deferredQuery sẽ giữ giá trị trước đó cho đến khi dữ liệu được tải, vì vậy SearchResults sẽ hiển thị kết quả cũ trong một khoảng thời gian.

Để làm cho nó rõ ràng hơn với người dùng, bạn có thể thêm một chỉ báo trực quan khi danh sách kết quả cũ được hiển thị:

<div style={{
opacity: query !== deferredQuery ? 0.5 : 1
}}>
<SearchResults query={deferredQuery} />
</div>

Nhập "a" trong ví dụ bên dưới, đợi kết quả tải và sau đó chỉnh sửa đầu vào thành "ab". Lưu ý rằng thay vì fallback của Suspense, bây giờ bạn thấy danh sách kết quả cũ bị làm mờ cho đến khi các kết quả mới được tải:

<div style={{
opacity: query !== deferredQuery ? 0.5 : 1
}}>
<SearchResults query={deferredQuery} />
</div>

Nhập "a" trong ví dụ bên dưới, đợi kết quả tải và sau đó chỉnh sửa đầu vào thành "ab". Lưu ý rằng thay vì fallback của Suspense, bây giờ bạn thấy danh sách kết quả cũ bị làm mờ cho đến khi các kết quả mới được tải:

import { Suspense, useState, useDeferredValue } from 'react';
import SearchResults from './SearchResults.js';

export default function App() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  const isStale = query !== deferredQuery;
  return (
    <>
      <label>
        Search albums:
        <input value={query} onChange={e => setQuery(e.target.value)} />
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <div style={{ opacity: isStale ? 0.5 : 1 }}>
          <SearchResults query={deferredQuery} />
        </div>
      </Suspense>
    </>
  );
}

Note

Cả giá trị được hoãn lại và Transitions cho phép bạn tránh hiển thị fallback của Suspense để ủng hộ các chỉ báo nội tuyến. Transitions đánh dấu toàn bộ bản cập nhật là không khẩn cấp, vì vậy chúng thường được sử dụng bởi các framework và thư viện bộ định tuyến để điều hướng. Mặt khác, các giá trị được hoãn lại chủ yếu hữu ích trong mã ứng dụng, nơi bạn muốn đánh dấu một phần của giao diện người dùng là không khẩn cấp và để nó “tụt lại phía sau” so với phần còn lại của giao diện người dùng.


Ngăn chặn việc ẩn nội dung đã hiển thị

Khi một thành phần tạm ngưng, ranh giới Suspense gần nhất sẽ chuyển sang hiển thị fallback. Điều này có thể dẫn đến trải nghiệm người dùng khó chịu nếu nó đã hiển thị một số nội dung. Hãy thử nhấn nút này:

import { Suspense, useState } from 'react';
import IndexPage from './IndexPage.js';
import ArtistPage from './ArtistPage.js';
import Layout from './Layout.js';

export default function App() {
  return (
    <Suspense fallback={<BigSpinner />}>
      <Router />
    </Suspense>
  );
}

function Router() {
  const [page, setPage] = useState('/');

  function navigate(url) {
    setPage(url);
  }

  let content;
  if (page === '/') {
    content = (
      <IndexPage navigate={navigate} />
    );
  } else if (page === '/the-beatles') {
    content = (
      <ArtistPage
        artist={{
          id: 'the-beatles',
          name: 'The Beatles',
        }}
      />
    );
  }
  return (
    <Layout>
      {content}
    </Layout>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}

Khi bạn nhấn nút, thành phần Router đã kết xuất ArtistPage thay vì IndexPage. Một thành phần bên trong ArtistPage tạm ngưng, vì vậy ranh giới Suspense gần nhất bắt đầu hiển thị fallback. Ranh giới Suspense gần nhất ở gần gốc, vì vậy toàn bộ bố cục trang web đã được thay thế bằng BigSpinner.

Để ngăn điều này, bạn có thể đánh dấu bản cập nhật trạng thái điều hướng là một Transition với startTransition:

function Router() {
const [page, setPage] = useState('/');

function navigate(url) {
startTransition(() => {
setPage(url);
});
}
// ...

Điều này cho React biết rằng quá trình chuyển đổi trạng thái không khẩn cấp và tốt hơn là tiếp tục hiển thị trang trước thay vì ẩn bất kỳ nội dung nào đã hiển thị. Bây giờ, việc nhấp vào nút sẽ “chờ” Biography tải:

import { Suspense, startTransition, useState } from 'react';
import IndexPage from './IndexPage.js';
import ArtistPage from './ArtistPage.js';
import Layout from './Layout.js';

export default function App() {
  return (
    <Suspense fallback={<BigSpinner />}>
      <Router />
    </Suspense>
  );
}

function Router() {
  const [page, setPage] = useState('/');

  function navigate(url) {
    startTransition(() => {
      setPage(url);
    });
  }

  let content;
  if (page === '/') {
    content = (
      <IndexPage navigate={navigate} />
    );
  } else if (page === '/the-beatles') {
    content = (
      <ArtistPage
        artist={{
          id: 'the-beatles',
          name: 'The Beatles',
        }}
      />
    );
  }
  return (
    <Layout>
      {content}
    </Layout>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}

Một Transition không đợi tất cả nội dung tải. Nó chỉ đợi đủ lâu để tránh ẩn nội dung đã hiển thị. Ví dụ: Layout của trang web đã được hiển thị, vì vậy sẽ rất tệ nếu ẩn nó sau một spinner tải. Tuy nhiên, ranh giới Suspense lồng nhau xung quanh Albums là mới, vì vậy Transition không đợi nó.

Note

Các bộ định tuyến hỗ trợ Suspense được mong đợi sẽ tự động gói các bản cập nhật điều hướng vào Transitions theo mặc định.


Cho biết rằng một Transition đang diễn ra

Trong ví dụ trên, khi bạn nhấp vào nút, không có dấu hiệu trực quan nào cho thấy một điều hướng đang được tiến hành. Để thêm một chỉ báo, bạn có thể thay thế startTransition bằng useTransition, cái mà cung cấp cho bạn một giá trị boolean isPending. Trong ví dụ dưới đây, nó được sử dụng để thay đổi kiểu tiêu đề trang web trong khi một Transition đang diễn ra:

import { Suspense, useState, useTransition } from 'react';
import IndexPage from './IndexPage.js';
import ArtistPage from './ArtistPage.js';
import Layout from './Layout.js';

export default function App() {
  return (
    <Suspense fallback={<BigSpinner />}>
      <Router />
    </Suspense>
  );
}

function Router() {
  const [page, setPage] = useState('/');
  const [isPending, startTransition] = useTransition();

  function navigate(url) {
    startTransition(() => {
      setPage(url);
    });
  }

  let content;
  if (page === '/') {
    content = (
      <IndexPage navigate={navigate} />
    );
  } else if (page === '/the-beatles') {
    content = (
      <ArtistPage
        artist={{
          id: 'the-beatles',
          name: 'The Beatles',
        }}
      />
    );
  }
  return (
    <Layout isPending={isPending}>
      {content}
    </Layout>
  );
}

function BigSpinner() {
  return <h2>🌀 Loading...</h2>;
}


Đặt lại ranh giới Suspense khi điều hướng

Trong quá trình Transition, React sẽ tránh ẩn nội dung đã hiển thị. Tuy nhiên, nếu bạn điều hướng đến một tuyến đường có các tham số khác nhau, bạn có thể muốn cho React biết đó là nội dung khác. Bạn có thể thể hiện điều này bằng một key:

<ProfilePage key={queryParams.id} />

Hãy tưởng tượng bạn đang điều hướng trong trang hồ sơ của người dùng và một cái gì đó tạm ngưng. Nếu bản cập nhật đó được gói trong một Transition, nó sẽ không kích hoạt fallback cho nội dung đã hiển thị. Đó là hành vi mong đợi.

Tuy nhiên, bây giờ hãy tưởng tượng bạn đang điều hướng giữa hai hồ sơ người dùng khác nhau. Trong trường hợp đó, việc hiển thị fallback sẽ có ý nghĩa. Ví dụ: dòng thời gian của một người dùng là nội dung khác so với dòng thời gian của một người dùng khác. Bằng cách chỉ định một key, bạn đảm bảo rằng React coi hồ sơ của những người dùng khác nhau là các thành phần khác nhau và đặt lại các ranh giới Suspense trong quá trình điều hướng. Các bộ định tuyến tích hợp Suspense sẽ tự động thực hiện điều này.


Cung cấp fallback cho các lỗi máy chủ và nội dung chỉ dành cho máy khách

Nếu bạn sử dụng một trong các API kết xuất máy chủ phát trực tuyến (hoặc một framework dựa trên chúng), React cũng sẽ sử dụng các ranh giới <Suspense> của bạn để xử lý các lỗi trên máy chủ. Nếu một thành phần đưa ra lỗi trên máy chủ, React sẽ không hủy bỏ quá trình kết xuất máy chủ. Thay vào đó, nó sẽ tìm thành phần <Suspense> gần nhất ở trên nó và bao gồm fallback của nó (chẳng hạn như một spinner) vào HTML máy chủ đã tạo. Người dùng sẽ thấy một spinner lúc đầu.

Trên máy khách, React sẽ cố gắng kết xuất lại thành phần tương tự. Nếu nó cũng gây ra lỗi trên máy khách, React sẽ đưa ra lỗi và hiển thị ranh giới lỗi gần nhất. Tuy nhiên, nếu nó không gây ra lỗi trên máy khách, React sẽ không hiển thị lỗi cho người dùng vì nội dung cuối cùng đã được hiển thị thành công.

Bạn có thể sử dụng điều này để chọn không kết xuất một số thành phần trên máy chủ. Để thực hiện việc này, hãy đưa ra một lỗi trong môi trường máy chủ và sau đó gói chúng trong một ranh giới <Suspense> để thay thế HTML của chúng bằng các fallback:

<Suspense fallback={<Loading />}>
<Chat />
</Suspense>

function Chat() {
if (typeof window === 'undefined') {
throw Error('Chat should only render on the client.');
}
// ...
}

HTML máy chủ sẽ bao gồm chỉ báo tải. Nó sẽ được thay thế bằng thành phần Chat trên máy khách.


Khắc phục sự cố

Làm cách nào để ngăn giao diện người dùng bị thay thế bằng fallback trong quá trình cập nhật?

Việc thay thế giao diện người dùng hiển thị bằng fallback tạo ra trải nghiệm người dùng khó chịu. Điều này có thể xảy ra khi một bản cập nhật khiến một thành phần tạm ngưng và ranh giới Suspense gần nhất đã hiển thị nội dung cho người dùng.

Để ngăn điều này xảy ra, hãy đánh dấu bản cập nhật là không khẩn cấp bằng cách sử dụng startTransition. Trong quá trình Transition, React sẽ đợi cho đến khi đủ dữ liệu được tải để ngăn chặn fallback không mong muốn xuất hiện:

function handleNextPageClick() {
// Nếu bản cập nhật này tạm ngưng, đừng ẩn nội dung đã hiển thị
startTransition(() => {
setCurrentPage(currentPage + 1);
});
}

Điều này sẽ tránh việc ẩn nội dung hiện có. Tuy nhiên, bất kỳ ranh giới Suspense mới được hiển thị nào vẫn sẽ hiển thị ngay lập tức các fallback để tránh chặn giao diện người dùng và cho phép người dùng xem nội dung khi nó có sẵn.

React sẽ chỉ ngăn chặn các fallback không mong muốn trong quá trình cập nhật không khẩn cấp. Nó sẽ không trì hoãn việc hiển thị nếu đó là kết quả của một bản cập nhật khẩn cấp. Bạn phải chọn tham gia bằng một API như startTransition hoặc useDeferredValue.

Nếu bộ định tuyến của bạn được tích hợp với Suspense, nó sẽ tự động gói các bản cập nhật của nó vào startTransition.

function handleNextPageClick() {
// If this update suspends, don't hide the already displayed content
startTransition(() => {
setCurrentPage(currentPage + 1);
});
}

Điều này sẽ tránh việc ẩn nội dung hiện có. Tuy nhiên, bất kỳ ranh giới Suspense mới được hiển thị nào vẫn sẽ hiển thị ngay lập tức các fallback để tránh chặn giao diện người dùng và cho phép người dùng xem nội dung khi nó có sẵn.

React sẽ chỉ ngăn chặn các fallback không mong muốn trong quá trình cập nhật không khẩn cấp. Nó sẽ không trì hoãn việc hiển thị nếu đó là kết quả của một bản cập nhật khẩn cấp. Bạn phải chọn tham gia bằng một API như startTransition hoặc useDeferredValue.

Nếu bộ định tuyến của bạn được tích hợp với Suspense, nó sẽ tự động gói các bản cập nhật của nó vào startTransition.

<Suspense fallback={<Loading />}>
<Chat />
</Suspense>

function Chat() {
if (typeof window === 'undefined') {
throw Error('Chat should only render on the client.');
}
// ...
}

HTML máy chủ sẽ bao gồm chỉ báo tải. Nó sẽ được thay thế bằng thành phần Chat trên máy khách.

function handleNextPageClick() {
// If this update suspends, don't hide the already displayed content
startTransition(() => {
setCurrentPage(currentPage + 1);
});
}

Điều này sẽ tránh việc ẩn nội dung hiện có. Tuy nhiên, bất kỳ ranh giới Suspense mới được hiển thị nào vẫn sẽ hiển thị ngay lập tức các fallback để tránh chặn giao diện người dùng và cho phép người dùng xem nội dung khi nó có sẵn.

React sẽ chỉ ngăn chặn các fallback không mong muốn trong quá trình cập nhật không khẩn cấp. Nó sẽ không trì hoãn việc hiển thị nếu đó là kết quả của một bản cập nhật khẩn cấp. Bạn phải chọn tham gia bằng một API như startTransition hoặc useDeferredValue.

Nếu bộ định tuyến của bạn được tích hợp với Suspense, nó sẽ tự động gói các bản cập nhật của nó vào startTransition.