React Suspense 如何判断组件是否准备好渲染

han*_*ter 8 reactjs react-suspense react-lazy-load

我正在使用此博客文章<React.Suspense>中的数据获取。\n来自反应文档

\n
\n

Suspense 让你的组件在渲染之前等待一些东西

\n
\n

本文档中有更好的解释

\n
\n

React.Suspense允许您指定加载指示器,以防其下方树中的某些组件尚未准备好渲染

\n
\n

我了解到,<React.Suspense>如果组件尚未准备好渲染,则会显示指定为后备属性的加载指示器。

\n

但是我不明白 React 如何检查组件是否准备好渲染。根据这个文档

\n
\n

随着更多的数据流入,React 将重试渲染,每次它都可能能够进行 \xe2\x80\x9cdeeper\xe2\x80\x9d。

\n
\n

这是否意味着当数据从网络请求流入时,React 也会重新渲染?
\n并<React.Suspense>不断检查组件是否准备好渲染?

\n

Tho*_*128 3

React.Suspense依赖于带有特殊包装器的Promise 。实际上,我们使用React.lazy作为包装器。如果您有兴趣了解包装器的工作原理,请参阅下面的代码片段。

// Boilerplate for the snippet, usually live in index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);


// Main Component
function App() {
  return (
    <React.Suspense fallback={<LoadingPage />}>
      <RealPage />
    </React.Suspense>
  );
}

// Promise need to be monitored with a wrapper
function wrapPromise(promise) {
  let status = "pending";
  let result;
  let suspender = promise.then(
    (r) => {
      status = "success";
      result = r;
    },
    (e) => {
      status = "error";
      result = e;
    }
  );
  return {
    read() {
      if (status === "pending") {
        throw suspender;
      } else if (status === "error") {
        throw result;
      } else if (status === "success") {
        return result;
      }
    },
  };
}

// This is an example of a delayed process that
// uses `promise` to mock resource fetch
function delayedProcessExample() {
  // Wait for 3 seconds
  let promise = new Promise((resolve) => setTimeout(resolve, 3000))
    // Return an example result
    .then(() => "Hello, World!");

  return promise;
}

// The delayed process should be executed somewhere.
// If you put it in a component, then the App going to
// request indefinitely
const exampleResource = wrapPromise(delayedProcessExample());

// This is how you access the resource
function RealPage() {
  const exampleData = exampleResource.read();
  return <div>{exampleData}</div>;
}

// This is the fallback component
function LoadingPage() {
  return <div>Loading... Please Wait</div>;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

请注意包装器抛出suspender承诺。该表达式告诉React.Suspend有一个承诺需要等待。因此,基本上React.Suspend依靠 Promise 作为异常来等待数据。

资料来源: