React suspense是否有一种方法可以为回退组件应用淡入/淡出过渡效果?

16

我有一个使用MUI的React应用程序,目前我已经使用Spinner实现了suspense,当内容正在加载时,Spinner将成为fallback组件。我希望为fallback组件添加一个淡入/淡出转换效果,因为当前变化太突然了。

我的设置(针对这个问题的相关部分)如下:

依赖项

    "@glidejs/glide": "^3.4.1",
    "@material-ui/core": "4.8.3",
    "@material-ui/icons": "4.5.1",
    "@material-ui/lab": "4.0.0-alpha.39",
    "@material-ui/pickers": "3.2.10",
    "@types/autosuggest-highlight": "^3.1.0",
    "@types/jest": "^24.0.0",
    "@types/node": "^12.0.0",
    "@types/react": "^16.9.0",
    "@types/react-dom": "^16.9.0",
    "@types/react-redux": "^7.1.7",
    "autosuggest-highlight": "^3.1.1",
    "connected-react-router": "^6.8.0",
    "history": "^4.10.1",
    "node-sass": "^4.13.0",
    "react": "^16.12.0",
    "react-date-picker": "^8.0.0",
    "react-dom": "^16.12.0",
    "react-feather": "^2.0.3",
    "react-redux": "^7.2.0",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.3.0",
    "redux-devtools-extension": "^2.13.8",
    "redux-ducks-ts": "^1.0.9",
    "redux-logger": "^3.0.6",
    "redux-saga": "^1.1.3",
    "reselect": "^4.0.0",
    "styled-components": "^4.4.1",
    "typescript": "~3.7.2"

路由器阻止

这是应用程序的主路由器,它有一个RouteWithSubRoutes组件,该组件接收一个路由作为参数,并呈现一个react-render-dom路由组件,但基本上充当切换容器的路由器。

import React, { FC, Suspense } from "react";
import { Switch } from "react-router-dom";
import routes from "./routes";
import { Route, Redirect } from "react-router-dom";
import { SessionContainerProps } from "./types";

// Coponents
import RouteWithSubRoutes from "components/_shared/RouteWithSubRoutes";
import Footer from "components/_shared/Footer";
import SuspenseLoader from "components/_shared/SuspenseLoader";

const SessionContainer: FC<SessionContainerProps> = () => (
    <>
        <Suspense fallback={<SuspenseLoader />}>
            <Switch>
                {routes.map((route, i) => (
                    <RouteWithSubRoutes key={`${i}_${route.path}`} {...route} />
                ))}
                <Route path="/login/*">
                    <Redirect to="/login" />
                </Route>
            </Switch>
        </Suspense>
        <Footer />
    </>
);

export default SessionContainer;

SuspenseLoader组件详情

目前它是一个居中的MUI圆形进度(Spinner),带有白色背景,覆盖整个应用程序。

import React from "react";
import { CircularProgress } from "@material-ui/core";

const SuspenseLoader = () => {
    return (
        <div
            style={{
                position: "fixed",
                top: 0,
                left: 0,
                width: "100vw",
                height: "100vh",
                zIndex: 10000,
                backgroundColor: "#FFF",
                display: "flex",
                alignItems: "center",
                flexDirection: "column",
                justifyContent: "center",
                marginTop: "auto",
                marginBottom: "auto",
            }}
        >
            <CircularProgress
                size="6rem"
                style={{
                    color: "#e8eaef",
                    margin: 0,
                    padding: 0,
                }}
            />
        </div>
    );
};
export default SuspenseLoader;


在 CSS 中,您可以添加 @keyframes 并在不同的百分比处更改 opacity - upog
2
感谢@upog的回复,您知道在组件卸载时如何触发关键帧动画吗?也许我错过了一些明显的东西,整个解决方案比我想象的要简单,但是备用组件似乎没有像其他组件一样的正常生命周期方法,而且我无法触发CSS动画,因为我似乎无法控制(可见性)挂载/卸载事件。 - guido732
你现在找到解决方案了吗? - Spray'n'Pray
不好意思,我还没有找到有用的东西,我一直在处理备用/主要组件之间的突然转换。 - guido732
2
@Spray'n'Pray guido732,这里有一个使用React suspense实现延迟淡入淡出动画的示例,我之前做过(不确定是否适用于您的情况)。 - ford04
1个回答

2
我会尝试给出这个答案。我认为你需要使用几个东西。
你可能想要使用CSS过渡:
```html

你需要使用CSS过渡:

```
.suspenseComponent {
  opacity: 1;
  transition: opacity 1s;
}

.fade {
  opacity: 0;
}

这样,如果您稍后更改元素的不透明度,它将在1秒的持续时间内发生。

然后,您还需要使用useRef(我想),以便您可以跟踪该组件并手动更新不透明度。

import {useRef} from 'react'

const element = useRef(null)

...

<SuspenseComponent ref={element}/>

...

element.current.classList.add('fade')

// essentially the same thing as document.getElementById('suspense').classList.add('fade')

使用上述方法,您可以获取元素的引用,并向其添加或删除类,因此您可以将fade类添加到其中。
最后,您可以使用:
import {useEffect} from 'react'

const Example = () => {
  useEffect(() => {
    // anything here will execute on component mount

    return () => {
      // anything you return here will execute on component unmount
    }
  }, [])
}

我自己没有构建过,但我认为你应该能够在组件挂载时应用不透明度类,以便它在1秒内过渡进入,然后在 useEffect 卸载时,如果您删除类,则应在1秒内过渡出。

如果它立即重新加载组件,那么也许您还可以包括:

setTimeout(() => {
  // delay whatever is refreshing the page
}, 1000)

如果这有助于解决问题。

希望这些想法的结合能够帮助您取得一些进展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接