gpt4 book ai didi

css - 如何在 React.js 中解决 FOUC

转载 作者:太空宇宙 更新时间:2023-11-04 01:13:36 26 4
gpt4 key购买 nike

我已经从 create-react-app 构建了 react.js 网站。但是在生产模式下,存在 FOUC,因为在渲染 html 之后加载样式。

有什么办法可以解决吗?我一直在谷歌上搜索答案,但还没有找到合适的答案。

最佳答案

自由行动联盟

FOUC - 所谓的无样式内容的闪现 可能与解决此问题的许多尝试一样非常有问题。

进入正题

让我们考虑以下路由配置 ( react-router ):

...
<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>
...

其中 PageLayout 是一个简单的 hoc ,包含带有 page-layout 类的 div 包装器并返回它的子级。

下面我们重点介绍基于路由的组件渲染。通常你会使用 React Compoment 作为 component prop。但在我们的例子中,我们需要动态获取它,以应用有助于我们避免 FOUC 的功能。所以我们的代码将如下所示:

import asyncRoute from './asyncRoute'

const Home = asyncRoute(() => import('./Home'))
const Example = asyncRoute(() => import('./Example'))

...

<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>

...

为了清楚起见,我们还展示了 asyncRoute.js 模块的外观:

import React, { Component } from 'react'
import PropTypes from 'prop-types'

import Loader from 'components/Loader'

class AsyncImport extends Component {
static propTypes = {
load: PropTypes.func.isRequired,
children: PropTypes.node.isRequired
}

state = {
component: null
}

toggleFoucClass () {
const root = document.getElementById('react-app')
if (root.hasClass('fouc')) {
root.removeClass('fouc')
} else {
root.addClass('fouc')
}
}

componentWillMount () {
this.toggleFoucClass()
}

componentDidMount () {
this.props.load()
.then((component) => {
setTimeout(() => this.toggleFoucClass(), 0)
this.setState(() => ({
component: component.default
}))
})
}

render () {
return this.props.children(this.state.component)
}
}

const asyncRoute = (importFunc) =>
(props) => (
<AsyncImport load={importFunc}>
{(Component) => {
return Component === null
? <Loader loading />
: <Component {...props} />
}}
</AsyncImport>
)

export default asyncRoute

hasClass, addClass, removeClass are polyfills which operates on DOM class attribute.

Loader is a custom component which shows spinner.

为什么要setTimeout

只是因为我们需要在第二个 tick 中删除 fouc 类。否则它会像渲染组件一样发生。所以它不会起作用。

正如您在 AsyncImport 组件中看到的,我们通过添加 fouc 类修改了 React 根容器。为清楚起见,使用 HTML:

<html lang="en">
<head></head>
<body>
<div id="react-app"></div>
</body>
</html>

还有另一 block 拼图:

#react-app.fouc
.page-layout *
visibility: hidden

导入特定组件(即:HomeExample)时应用的 sass。

为什么不 display: none

因为我们希望所有依赖于父宽度、高度或任何其他 css 规则的组件都能正确呈现。

它是如何工作的?

主要假设是隐藏所有元素,直到组件准备好向我们展示呈现的内容。首先它触发 asyncRoute 函数,它向我们展示 Loader 直到 Component 安装和渲染。同时,在 AsyncImport 中,我们通过在 React 根 DOM 元素上使用 fouc 类来切换内容的可见性。当所有内容加载完毕后,就到了显示所有内容的时候了,因此我们删除了该类。

希望对您有所帮助!

感谢

article ,动态导入的想法(我认为)来自 react-loadable .

来源

https://turkus.github.io/2018/06/06/fouc-react/

关于css - 如何在 React.js 中解决 FOUC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50694118/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com