React suspense 防止后备微调器闪烁

Posted

技术标签:

【中文标题】React suspense 防止后备微调器闪烁【英文标题】:React suspense prevent flashing of fallback spinner 【发布时间】:2019-12-15 16:42:18 【问题描述】:

我想知道是否有一种好方法可以防止反应中的后备闪现。我正在使用反应路由器,问题是当一个组件被挂起时,后备加载程序会非常快地闪烁,这很烦人。我在这里看到了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 具有开箱即用的基本相同功能。

【问题讨论】:

也许这就是你想要的:***.com/a/58971161/6548802 加载器只有在加载大于 300 毫秒时才会显示。您必须自定义此延迟加载程序以显示您想要的内容或通用组件。 我遇到了同样的问题。但我正在使用 react-snap 生成静态版本。如果情况相同,我会根据用户视口解决从顶部组件中删除惰性并获得部分闪存的问题。 github.com/facebook/react/issues/14438 这能回答你的问题吗? React suspense/lazy delay? @KevinAshworth 您发布的链接基本上与我的问题中的代码完全相同,如果您阅读该问题,我会解决它。问题是页面在超时期间没有任何内容,页面挂起并跳来跳去。所以不,它不能回答这个问题。 【参考方案1】:

我最近遇到了同样的问题,我最终实现了一个组件,用于悬念的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>

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

【讨论】:

【参考方案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>
  );

【讨论】:

这基本上与我上面发布的代码完全相同。这将有什么帮助。可能你没看懂问题。当组件加载但暂停时,反应显示微调器非常快,然后将其带走。这种快速闪烁然后通过悬念移除微调器是我试图避免的。我不需要帮助编写微调器代码。

以上是关于React suspense 防止后备微调器闪烁的主要内容,如果未能解决你的问题,请参考以下文章

React Suspense 延迟加载没有回退

CSS剪辑导致闪烁的微调器?

Android防止双击微调器

在 React.js 中加载异步数据时防止 UI 闪烁

React - 节流/去抖动微调器(加载消息) - 不显示请求是不是快于 X 毫秒

排毒:使用停止按钮测试 React-Native 微调器