material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

[examples/remix-with-typescript] React 18 version example is required.

Open hiuny opened this issue 3 years ago • 7 comments

Duplicates

  • [X] I have searched the existing issues

Latest version

  • [X] I have tested the latest version

Current behavior 😯

A function called renderToPipeableStream() is used in entry.server.ts of remix 1.7.0 using react 18.2.0. However, this part is not reflected in the remix example of mui. Can you please reflect it?

// npx create-remix@latest (at 2022-09-02)
// app/entry.server.tsx

import { PassThrough } from "stream";
import type { EntryContext } from "@remix-run/node";
import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import { renderToPipeableStream } from "react-dom/server";

const ABORT_DELAY = 5000;

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  return new Promise((resolve, reject) => {
    let didError = false;

    const { pipe, abort } = renderToPipeableStream(
      <RemixServer context={remixContext} url={request.url} />,
      {
        onShellReady: () => {
          const body = new PassThrough();

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(body, {
              headers: responseHeaders,
              status: didError ? 500 : responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError: (err) => {
          reject(err);
        },
        onError: (error) => {
          didError = true;

          console.error(error);
        },
      }
    );

    setTimeout(abort, ABORT_DELAY);
  });
}
// https://github.com/mui/material-ui/blob/master/examples/remix-with-typescript/app/entry.server.tsx

import * as React from 'react';
import { renderToString } from 'react-dom/server';
import { RemixServer } from 'remix';
import type { EntryContext } from 'remix';
import createEmotionCache from './src/createEmotionCache';
import theme from './src/theme';
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider } from '@mui/material/styles';
import { CacheProvider } from '@emotion/react';
import createEmotionServer from '@emotion/server/create-instance';

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext,
) {
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  const MuiRemixServer = () => (
    <CacheProvider value={cache}>
      <ThemeProvider theme={theme}>
        {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
        <CssBaseline />
        <RemixServer context={remixContext} url={request.url} />
      </ThemeProvider>
    </CacheProvider>
  );

  // Render the component to a string.
  const html = renderToString(<MuiRemixServer />);

  // Grab the CSS from emotion
  const { styles } = extractCriticalToChunks(html);

  let stylesHTML = '';

  styles.forEach(({ key, ids, css }) => {
    const emotionKey = `${key} ${ids.join(' ')}`;
    const newStyleTag = `<style data-emotion="${emotionKey}">${css}</style>`;
    stylesHTML = `${stylesHTML}${newStyleTag}`;
  });

  // Add the Emotion style tags after the insertion point meta tag
  const markup = html.replace(
    /<meta(\s)*name="emotion-insertion-point"(\s)*content="emotion-insertion-point"(\s)*\/>/,
    `<meta name="emotion-insertion-point" content="emotion-insertion-point"/>${stylesHTML}`,
  );

  responseHeaders.set('Content-Type', 'text/html');

  return new Response(`<!DOCTYPE html>${markup}`, {
    status: responseStatusCode,
    headers: responseHeaders,
  });
}

Expected behavior 🤔

I hope that the contents mentioned in 'Current behavior' are reflected.

Steps to reproduce 🕹

There are no special reproduction steps.

Context 🔦

As of now (2022-09-02) I want to use mui in the remix of the latest version (1.7.0).

Your environment 🌎

npx @mui/envinfo
  System:
    OS: Linux 5.15 Ubuntu 20.04.4 LTS (Focal Fossa)
  Binaries:
    Node: 14.20.0 - ~/.nvm/versions/node/v14.20.0/bin/node
    Yarn: Not Found
    npm: 6.14.17 - ~/.nvm/versions/node/v14.20.0/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    @emotion/react: 11.10.4 => 11.10.4 
    @emotion/styled: 11.10.4 => 11.10.4 
    @mui/base:  5.0.0-alpha.95 
    @mui/core-downloads-tracker:  5.10.3 
    @mui/icons-material: 5.10.3 => 5.10.3 
    @mui/material: 5.10.3 => 5.10.3 
    @mui/private-theming:  5.10.3 
    @mui/styled-engine:  5.10.3 
    @mui/system: 5.10.3 => 5.10.3 
    @mui/types:  7.2.0 
    @mui/utils:  5.10.3 
    @types/react: 18.0.15 => 18.0.15 
    react: 18.2.0 => 18.2.0 
    react-dom: 18.2.0 => 18.2.0 
    typescript: 4.7.4 => 4.7.4

hiuny avatar Sep 02 '22 01:09 hiuny

@hiuny Thanks for the feedback. Do you want to submit a PR to update the example?

siriwatknp avatar Sep 02 '22 07:09 siriwatknp

@siriwatknp I'd love to, but I don't know how the renderToPipeableStream() function works, so it's going to be hard right now. I think it would be quick if someone who knows the 18 version of react helped.

hiuny avatar Sep 02 '22 07:09 hiuny

Agree, the example should be updated according to the latest template from Remix. Would be great if someone from the community, especially if that someone uses Remix can handle it.

mnajdova avatar Sep 22 '22 11:09 mnajdova

Please update the example. I have an issue with remix.js

zolzaya avatar Sep 23 '22 06:09 zolzaya

There is an ongoing PR for udpating the Remix example - https://github.com/mui/material-ui/pull/34407

mnajdova avatar Sep 23 '22 06:09 mnajdova

I don't think it's possible yet to update examples, as Emotion is not compatible with React 18 SSR Streaming (renderToPipeableStream) and neither is Styled Components.

igorbt avatar Sep 28 '22 08:09 igorbt

this is stuck or any one knows how is it going ?

joacub avatar Dec 13 '22 18:12 joacub

Install remix with JS instead of TSX would work.

Andrehatlo avatar Dec 22 '22 14:12 Andrehatlo

I found this example works well https://stackblitz.com/edit/github-ut9vkm

guatedude2 avatar Jan 19 '23 01:01 guatedude2

Is this still stuck?

yannick-softwerft avatar Sep 11 '23 15:09 yannick-softwerft

Give this a shot, worked for me: https://github.com/remix-run/examples/blob/main/chakra-ui/app/entry.server.tsx

tmo207 avatar Dec 29 '23 22:12 tmo207

Give this a shot, worked for me: https://github.com/remix-run/examples/blob/main/chakra-ui/app/entry.server.tsx

For me this emotionServer.renderStylesToNodeStream() creates a NodeJS.ReadWriteStream that is not compatible with the body parameter of the Response constructor. Does anyone have a suggestion how to convert a NodeJS.ReadWriteStream to a ReadableStream<Uint8Array>?

yannickpschroeder avatar Jan 18 '24 09:01 yannickpschroeder

@tmo207

Give this a shot, worked for me: https://github.com/remix-run/examples/blob/main/chakra-ui/app/entry.server.tsx

Does MUI also use Emotion?

tombohub avatar Feb 23 '24 15:02 tombohub