Как разрешить FOUC в React.js

Я создал сайт response.js из приложения create-response-app. Но в производственном режиме есть FOUC, потому что стили загружаются после рендеринга HTML.

Есть ли способ решить эту проблему? Я искал ответы в Google, но пока не нашел подходящего.

Вы выбросили свой проект?

Yevhenii Herasymchuk 05.06.2018 09:13
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
1
1
3 122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

FOUC

FOUC - так называемый Вспышка не стилизованного содержания может быть столь же проблематичным, как и многие попытки решить эту проблему.

К точке

Рассмотрим следующую конфигурацию маршрутизации (реагирующий маршрутизатор):

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

где PageLayout - это простой hoc, содержащий обертку div с классом page-layout и возвращающий его потомков.

Теперь давайте сосредоточимся на рендеринге компонентов на основе маршрута. Обычно вы использовали бы в качестве component опору React Compoment. Но в нашем случае нам нужно получить его динамически, чтобы применить функцию, которая помогает нам избежать 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?

Просто потому, что нам нужно убрать класс fouc во второй галочке. В противном случае это произошло бы так же, как рендеринг Компонента. Так что это не сработает.

Как вы можете видеть в компоненте AsyncImport, мы модифицируем корневой контейнер реакции, добавляя класс fouc. Итак, HTML для ясности:

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

и еще одна загадка:

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

sass, применяемый при импорте определенного компонента (например: Home, Example).

Почему не display: none?

Потому что мы хотим, чтобы все компоненты, которые полагаются на родительскую ширину, высоту или любое другое правило CSS, правильно отображались.

Как это работает?

Основное предположение заключалось в том, чтобы скрыть все элементы до тех пор, пока композиция не будет готова показать нам визуализированный контент. Сначала он запускает функцию asyncRoute, которая показывает нам Loader, пока Component не смонтирует и не отрендерит. Тем временем в AsyncImport мы переключаем видимость контента с помощью класса fouc на корневом элементе DOM реакции. Когда все загружается, пора все показать, поэтому мы удаляем этот класс.

Надеюсь, это поможет!

Благодаря

Это статья, идея динамического импорта которого была взята (я думаю) из реагирующий.

Источник

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

Один вопрос - где мне разместить css для 'fouc', 'page-layout'

Thunderbolt Engineer 08.06.2018 00:18

@ThunderboltEngineer, вы можете поместить его даже в свой HTML-код в голове, но помните, что это нахально.

turkus 08.06.2018 07:24

Другие вопросы по теме