材质用户界面:页面初始加载时闪烁Razzle

问题描述

我已经在我的服务器端渲染应用程序中集成了材料UI,并遵循了here给出的代码。实质性的UI css已添加到服务器端本身的html中。

但是,在初始加载时,未应用材料ui样式,这会导致其闪烁。

我尝试将<cssbaseline>与以下代码一起使用,但没有发现任何区别。

这是我的代码: server.js

import App from '../common/containers/App';
import { Provider } from 'react-redux';
import React from 'react';
import configureStore from '../common/store/configureStore';
import express from 'express';
import qs from 'qs';
import { renderToString } from 'react-dom/server';
import serialize from 'serialize-javascript';
import { StaticRouter,matchPath } from 'react-router-dom';
import {theme} from '../theme';
import { ServerStyleSheets,ThemeProvider } from '@material-ui/styles';
import routes from './routes'
import "../common/assets/SCSS/app.scss";

const assets = require(process.env.RAZZLE_ASSETS_MANIFEST);
const server = express();
server
  .disable('x-powered-by')
  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
  .get('/*',(req,res) => {
    const activeRoute = routes.find((route) => matchPath(req.url,route)) || {}
    const promise = activeRoute.fetchInitialData
      ? activeRoute.fetchInitialData(req.path)
      : Promise.resolve()
    promise.then((apiResult) => {
      const sheets = new ServerStyleSheets();
      const counter =  apiResult || 0;
      const preloadedState = { counter };
      const store = configureStore(preloadedState);
      const context = {};
      const markup = renderToString(
         sheets.collect(
           <Provider store={store}>
            <ThemeProvider theme={theme}>
              <StaticRouter location={req.url} context={context}>
                <App />
              </StaticRouter>
            </ThemeProvider>
          </Provider>
      ));
   const css = sheets.toString();
      const finalState = store.getState();
      const html = `<!doctype html>
          <html lang="">
          <head>
              ${assets.client.css
                ? `<link rel="stylesheet" href="${assets.client.css}">`
                : ''}
                ${css ? `<style id='jss-ssr'>${css}</style>` : ''}
                ${process.env.NODE_ENV === 'production'
                  ? `<script src="${assets.client.js}" defer></script>`
                  : `<script src="${assets.client.js}" defer crossorigin></script>`}
          </head>
          <body>
              <div id="root">${markup}</div>
              <script>
                window.__PRELOADED_STATE__ = ${serialize(finalState)}
              </script>
          </body>
      </html>`
 res.send(html);
    });
  });

export default server;

Client.js

import React,{useEffect} from 'react';
import { hydrate } from 'react-dom';
import {theme} from '../theme';
import { ThemeProvider } from '@material-ui/styles';
import { Provider } from 'react-redux';
import configureStore from '../common/store/configureStore';
import App from '../common/containers/App';
import { browserRouter } from "react-router-dom";
import "../common/assets/SCSS/app.scss";
import * as serviceWorker from '../serviceWorker';
import CssBaseline from '@material-ui/core/CssBaseline';

const store = configureStore(window.__PRELOADED_STATE__);
const Client = () => {
  useEffect(() => {
   
    const jssstyles = document.querySelector('#jss-ssr');
    if (jssstyles) {
      jssstyles.parentElement.removeChild(jssstyles);
    }
  },[]);

  return(
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <browserRouter>
          <App />
        </browserRouter>
      </ThemeProvider>
    </Provider>
  );

}


hydrate(<Client />,document.getElementById('root'));

解决方法

这是由于您的客户端代码在生成客户端样式之前删除了服务器生成的样式。

react-dom提供的hydrate函数具有第3个参数,该参数是在应用程序水化完成后调用的回调函数。

此回调函数应用于确保应用程序已完成水合作用并已生成客户端样式。

import React,{useEffect} from 'react';
import { hydrate } from 'react-dom';
import {theme} from '../theme';
import { ThemeProvider } from '@material-ui/styles';
import { Provider } from 'react-redux';
import configureStore from '../common/store/configureStore';
import App from '../common/containers/App';
import { BrowserRouter } from "react-router-dom";
import "../common/assets/SCSS/app.scss";
import * as serviceWorker from '../serviceWorker';
import CssBaseline from '@material-ui/core/CssBaseline';

const store = configureStore(window.__PRELOADED_STATE__);

const Client = () => {
  return(
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </ThemeProvider>
    </Provider>
  );

}


hydrate(
    <Client />,document.getElementById('root'),() => {
        const jssStyles = document.querySelector('#jss-ssr');

        if (jssStyles) {
            jssStyles.parentElement.removeChild(jssStyles);
        }
    }
);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...