Skip to content

Render method does not return the finished HTML, rather the un hydrated HTML when used in react + vite app #3181

@karansethia123

Description

@karansethia123

What versions are you using? (if relevant)

@react-email/render -> 2.0.4

Describe the Bug

When the rendered template is copied to clipboard or logged to the console, HTML contains scripts and other elements that result in a broken html being copied to the clipboard. But when copied for the second time, the html returned works which implies a streaming issue happens in the browser.
Is render utility only meant for server side and not browsers, as I am running it in vite react app

What is affected (leave empty if unsure)

Render Utility

Link to the code that reproduces this issue

    const rendered = await pretty(await render(<FinalTemplate content={str} />));
   navigator.clipboard.writeText(rendered);
   toast.message("Email Template copied");

const tailwindConfig = {
  presets: [pixelBasedPreset],
  theme: {
    extend: {
      colors: {
        brand: "#007291",
      },
    },
  },
}



type Props = {
  content: string,
}

export const FinalTemplate = ({ content }: Props) => {


  return <Html>
    <Head />
    <Tailwind config={tailwindConfig}>
      <Body className="bg-white font-google">
        <Container className="my-[30px] mx-auto bg-white rounded-[5px] overflow-hidden">
          <Section className="bg-[#0048C2] p-8 text-center">
            <Img
              src=""
              width="260"
              className="mx-auto block"
            />
          </Section>

          <Section className="px-10">
            <Text className="text-sm leading-[22px] text-[#3c4043]">
              {content}
            </Text>
          </Section>

          <Section
            className="text-center px-8 pt-10 pb-6 bg-[#0048C2]"
          >

            {/* Logo */}
            <Row>
              <Column className="text-center pb-6">
                <Img
                  src=""
                  width="200"
                  style={{ margin: "0 auto", display: "block" }}
                />
              </Column>
            </Row>

            {/* Thin divider */}
            <Row>
              <Column className="px-16 pb-6">
                <div
                  style={{
                    height: 1,
                    backgroundColor: "rgba(255,255,255,0.15)",
                  }}
                />
              </Column>
            </Row>

            {/* Social Icons */}
            <Row>
              <Column className="text-center pb-5">
                {/* Facebook */}
                <Link href="https://facebook.com" style={{ display: "inline-block", margin: "0 10px" }}>
                  <Img
                    src="https://cdn.simpleicons.org/facebook/white"
                    alt="Facebook"
                    width="24"
                    height="24"
                    style={{ display: "inline-block" }}
                  />
                </Link>

                {/* Instagram */}
                <Link href="https://instagram.com" style={{ display: "inline-block", margin: "0 10px" }}>
                  <Img
                    src="https://cdn.simpleicons.org/instagram/white"
                    alt="Instagram"
                    width="24"
                    height="24"
                    style={{ display: "inline-block" }}
                  />
                </Link>
              </Column>
            </Row>

            {/* App Store Badges */}
            <Row>
              <Column className="text-center pb-7">
                {/* App Store */}
                <Link
                  href="https://apps.apple.com"
                  style={{
                    display: "inline-block",
                    marginRight: 6,
                    backgroundColor: "rgba(255,255,255,0.1)",
                    borderRadius: 8,
                    padding: "8px 16px",
                    border: "1px solid rgba(255,255,255,0.25)",
                  }}
                >
                  <Img
                    src="https://cdn.simpleicons.org/appstore/white"
                    alt="App Store"
                    width="20"
                    height="20"
                    style={{ display: "inline-block", verticalAlign: "middle", marginRight: 8 }}
                  />
                  <span
                    style={{
                      fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                      color: "#ffffff",
                      fontSize: "12px",
                      fontWeight: 600,
                      verticalAlign: "middle",
                      letterSpacing: "0.04em",
                      textTransform: "uppercase",
                    }}
                  >
                    App Store
                  </span>
                </Link>

                {/* Google Play */}
                <Link
                  href="https://play.google.com"
                  style={{
                    display: "inline-block",
                    marginLeft: 6,
                    backgroundColor: "rgba(255,255,255,0.1)",
                    borderRadius: 8,
                    padding: "8px 16px",
                    border: "1px solid rgba(255,255,255,0.25)",
                  }}
                >
                  <Img
                    src="https://cdn.simpleicons.org/googleplay/white"
                    alt="Google Play"
                    width="20"
                    height="20"
                    style={{ display: "inline-block", verticalAlign: "middle", marginRight: 8 }}
                  />
                  <span
                    style={{
                      fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                      color: "#ffffff",
                      fontSize: "12px",
                      fontWeight: 600,
                      verticalAlign: "middle",
                      letterSpacing: "0.04em",
                      textTransform: "uppercase",
                    }}
                  >
                    Google Play
                  </span>
                </Link>
              </Column>
            </Row>

            {/* Thin divider */}
            <Row>
              <Column className="px-16 pb-6">
                <div
                  style={{
                    height: 1,
                    backgroundColor: "rgba(255,255,255,0.15)",
                  }}
                />
              </Column>
            </Row>

            {/* Hours of Operation */}
            <Row>
              <Column className="text-center pb-1">
                <Text
                  className="m-0 text-[14px] font-semibold"
                  style={{
                    fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                    color: "#ffffff",
                  }}
                >
                  Hours of Operation
                </Text>
              </Column>
            </Row>
            <Row>
              <Column className="text-center pb-5">
                <Text
                  className="m-0 text-[13px]"
                  style={{
                    fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                    color: "#a8bde8",
                  }}
                >
                  Mon – Sun: 8am – 9pm
                </Text>
              </Column>
            </Row>

            {/* Address */}
            <Row>
              <Column className="text-center px-6 pb-2">
                <Text
                  className="m-0 text-[13px] leading-relaxed"
                  style={{
                    fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                    color: "#a8bde8",
                  }}
                >
                  10880, Mailbu Point
                  <br />
                  California - 90265 United States
                </Text>
              </Column>
            </Row>

            {/* Phone */}
            <Row>
              <Column className="text-center pb-6">
                <Link
                  href="tel:+1908487374837"
                  className="text-[13px] no-underline"
                  style={{
                    fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                    color: "#a8bde8",
                  }}
                >
                  1908487374837
                </Link>
              </Column>
            </Row>

            {/* Thin divider */}
            <Row>
              <Column className="px-16 pb-5">
                <div
                  style={{
                    height: 1,
                    backgroundColor: "rgba(255,255,255,0.1)",
                  }}
                />
              </Column>
            </Row>

            {/* Copyright */}
            <Row>
              <Column className="text-center pb-2">
                <Text
                  className="m-0 text-[11px]"
                  style={{
                    fontFamily: "'Barlow', 'Helvetica Neue', sans-serif",
                    color: "#4a6aab",
                  }}
                >
                  Copyright © 
                </Text>
              </Column>
            </Row>

          </Section>


        </Container>
      </Body>
    </Tailwind>
  </Html>
};

export default FinalTemplate;

To Reproduce

To reproduce the issue

  • install the folowing packages on vite + react + typescript app
    "@react-email/components": "1.0.10",
    "@react-email/render": "^2.0.4",
    "@react-email/tailwind": "^2.0.6",
  • Create an email template using the templates from the docs,
  • Add a prop that that passes down a string content
  • Call render function on a click of a button ( see code above )

Expected Behavior

The string returned after awaiting the render utility should ideally be a proper HTML with no scripts or broken HTML

What's your node version? (if relevant)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions