mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.52k stars 32.18k forks source link

Styles missing when js loaded #36557

Open doublelam opened 1 year ago

doublelam commented 1 year ago

Duplicates

Latest version

Steps to reproduce 🕹

Hi, I am encountering the style-missing issue on client side, but the server-rendered correctly, no idea why it happend. Many thanks for your help!

My server.js:

import React from 'react';
import Koa from 'koa';
import Router from '@koa/router';
import { renderToPipeableStream } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import App from '@root/app';
import Shell from '@root/shell';

const app = new Koa();
const router = new Router();

router.get('/(.*)', async (ctx) => {
  const pipePromise: Promise<ReturnType<typeof renderToPipeableStream>['pipe']> = new Promise((resolve, reject) => {
    const { pipe } = renderToPipeableStream(
      <App>
        <StaticRouter location={ctx.URL}>
          <Shell />
        </StaticRouter>
      </App>,
      {
        bootstrapScripts: [
          'https://unpkg.com/react@18.2.0/umd/react.development.js',
          'https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js',
          '/static/bundle.js',
        ],
        onShellReady() {
          resolve(pipe);
        },
        onShellError(err) {
          reject(err);
        },
        onError(error) {
          reject(error);
        },

      },
    );
  });
  const pipe = await pipePromise;
  ctx.status = 200;
  pipe(ctx.res);
});

app.use(router.routes())
  .use(router.allowedMethods());

app.listen(1001);

My client scripts: index.tsx:

import * as React from 'react';
import { hydrateRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './app';
import Shell from './shell';

hydrateRoot(
  document,
  <App>
    <React.StrictMode>
      <BrowserRouter>
        <Shell />
      </BrowserRouter>
    </React.StrictMode>
  </App>,
);

shell.tsx:

import { CssVarsProvider } from '@mui/joy';
import React from 'react';
import AppRouter from './app-router';
import theme from './themes';

const Shell = () => (
  <CssVarsProvider theme={theme} defaultMode="system">
    <AppRouter />
  </CssVarsProvider>
);

export default Shell;

app-router.tsx:

import React from 'react';
import {
  Route,
  Routes,
} from 'react-router-dom';
import ErrorPage from './pages/error';
import Test from './pages/test';
import Home from './pages/home';

function AppRouter() {
  return (
    <Routes>
      <Route errorElement={<ErrorPage />} path="/">
        <Route index element={<Home />} />
        <Route path="test" element={<Test />} />
        <Route path="*" element={<ErrorPage />} />
      </Route>
    </Routes>
  );
}

export default AppRouter;

home.tsx:

import {
  Button, List, ListItem, ListItemButton, useTheme,
} from '@mui/joy';
import React from 'react';
import { useNavigate } from 'react-router-dom';
import styles from './pages.module.less';

const Home = () => {
  const nav = useNavigate();
  const theme = useTheme();

  return (
    <>
      <header>
        <List component="nav">
          <ListItem>
            <ListItemButton onClick={() => nav('/test')}>test</ListItemButton>
          </ListItem>
          <ListItem>2</ListItem>
          <ListItem>3</ListItem>
        </List>
      </header>
      <main>
        <section>
          <div
            className={styles.test}
            style={{
              width: 100,
              height: 100,
              backgroundColor: theme.palette.success[900],
            }}
          />
          <Button>test button</Button>
        </section>
      </main>
    </>
  );
};

export default Home;

I have no idea why the server side rendered correctly but the local client miss the styles when js loaded

Current behavior 😯

client side is missing the MUI styles

Expected behavior 🤔

client should render same as server

Context 🔦

No response

Your environment 🌎

npx @mui/envinfo ``` Don't forget to mention which browser you used. Output from `npx @mui/envinfo` goes here. ``` System: OS: macOS 12.6.3 Binaries: Node: 16.18.1 - ~/.nvm/versions/node/v16.18.1/bin/node Yarn: 1.9.2 - ~/.yvm/shim/yarn npm: 8.19.2 - ~/.nvm/versions/node/v16.18.1/bin/npm Browsers: Chrome: 111.0.5563.64 Edge: Not Found Firefox: 107.0.1 Safari: 16.3 npmPackages: @emotion/react: 11.10.6 @emotion/styled: 11.10.6 @mui/base: 5.0.0-alpha.121 @mui/core-downloads-tracker: 5.11.13 @mui/joy: 5.0.0-alpha.71 @mui/private-theming: 5.11.13 @mui/styled-engine: 5.11.11 @mui/system: 5.11.13 @mui/types: 7.2.3 @mui/utils: 5.11.13 @types/react: 18.0.28 react: 18.2.0 react-dom: 18.2.0 typescript: 4.9.5
mj12albert commented 1 year ago

@doublelam At a glance, you may be missing CacheProvider on both the server side and client side, see this doc: https://mui.com/material-ui/guides/server-rendering/#the-client-side

thomasjm commented 1 year ago

You're using React 18's renderToPipeableStream, which is currently unsupported by both of Material UI's main styling engines, Emotion and styled-components.

The threads about this can be found here and here.

AFAICT, there is no way to use Material UI with React 18 streaming rendering, other than some hacks that have been pasted into various GitHub comments.

I'm not sure why there isn't a mention of this in the Material UI docs, or even a dedicated issue for it. Am I missing a way to make this work?

WillSmithTE commented 11 months ago

@thomasjm they're working on mui/zero, and apparently will have an alpha version out in november.

https://github.com/mui/material-ui/issues/38137 See mui/zero references: https://github.com/mui/material-ui/releases

ignacio-dev commented 5 months ago

Did you ever manage to solve this? I'm facing the same issue with a Hydrogen project