17

我想知道是否有一种好方法可以防止反应中的后备闪现。我正在使用反应路由器,问题是当一个组件被挂起时,后备加载程序会非常快地闪烁,这很烦人。我在这里看到了答案React suspense/lazy delay? 如下所示:

const Home = lazy(() => {
  return Promise.all([
    import('./components/Home'),
    new Promise(resolve => setTimeout(resolve, 500))
  ]).then(([moduleExports]) => moduleExports);
});

但我的问题是我有一个具有透明背景的覆盖加载微调器,并且在解决承诺之前组件实际上不会加载。这会使页面在没有内容的情况下挂起半秒钟,实际上比微调器的闪烁更烦人。

所以我想问题是有没有人找到解决这个问题的好方法。我真的很想在页面中添加类似 nprogress 的内容,但不知道如何使用 React.suspense 实现它。我可能只需要重新使用 react loadable,但我真的不想在 react 具有开箱即用的基本相同功能时使用。

4

2 回答 2

2

我最近遇到了同样的问题,最终我实现了一个用于fallback悬念的组件。

这个想法很简单,只是在一定时间内不显示任何东西,然后显示加载程序。因此,假设在 300 毫秒内不会显示任何内容,延迟后它应该显示(在这种情况下)ContentLoader或任何您喜欢的内容。

在打字稿中lazy-loader.ts

import { FC, useEffect, useState } from 'react';
import ContentLoader from './content-loader'; // or any spinner component

export interface LazyLoaderProps {
  delay?: number;
}

const LazyLoader: FC<LazyLoaderProps> = ({
  delay = 250,
  ...props
}) => {
  const [show, setShow] = useState(false);

  useEffect(() => {
    const timeout = setTimeout(() => {
      setShow(true);
    }, delay);
    return () => {
      clearTimeout(timeout);
    };
  }, [delay]);

  return show ? <ContentLoader {...props} /> : null;
};

export { LazyLoader as default };

然后像这样使用

import LazyLoader from "./lazy-loader"
// ...
<Suspense fallback={<LazyLoader delay={300} />}>...</Suspense>

这不会延迟进口。(我也认为这不是最佳的)让我知道这是否有帮助。

于 2021-01-05T19:06:01.813 回答
-2
import React, { Suspense, lazy } from "react";

const Home = lazy(() => {
  return Promise.all([
    import("./home"),
    new Promise(resolve => setTimeout(resolve, 300))
  ]).then(([moduleExports]) => moduleExports);
});

function FullSpinner() {
  return (
    {/**  full spinner jsx goes here */}
    <div className="full-spinner">
      <p>loading....</p>
    </div>
  )
}

function App() {
  return (
    <div className="App">
      <h1>app component</h1>
      <Suspense fallback={<FullSpinner />}>
        <Home />
      </Suspense>
    </div>
  );
}

编辑:

import React, { Suspense, lazy, useState, useEffect } from "react";

const Home = lazy(() => {
  return Promise.all([
    import("./home"),
    new Promise(resolve => setTimeout(resolve, 500))
  ]).then(([moduleExports]) => moduleExports);
});

function FullSpinner() {
  return (
    <div className="full-spinner">
      <p>loading....</p>
    </div>
  );
}

const LazyLoading = ({ delay, loader: Loader, children }) => {
  const [ready, setReady] = useState(false);
  useEffect(() => {
    setTimeout(() => setReady(true), delay);
  }, [delay]);
  return ready ? (
    <Suspense fallback={<Loader />}>{children}</Suspense>
  ) : (
    <Loader />
  );
};

function App() {
  return (
    <div className="App">
      <h1>app component</h1>
      <LazyLoading delay={2000} loader={FullSpinner}>
        <Home />
      </LazyLoading>
    </div>
  );
}
于 2019-08-08T05:34:29.260 回答