noob_learner
noob_learner

Reputation: 1

Next.js: Import Error with react-email - renderToReadableStream Not Exported

I am working on a project in Next.jsand implementing a signup functionality. When I submit the signup details using the submit button, I encounter the following error:

Import trace for requested module:./node_modules/@react-email/components/node_modules/@react-email/render/dist/index.mjs./node_modules/@react-email/components/dist/index.mjs./emails/VerificationEmail.tsx./src/helpers/sendVerificationEmail.ts./src/app/api/sign-up/route.ts⨯ ./node_modules/@react-email/components/node_modules/@react-email/render/dist/index.mjsAttempted import error: 'renderToReadableStream' is not exported from 'react-dom/server' (imported as 'renderToReadableStream').

Code Using react-email:

import {
    Html,
    Head,
    Font,
    Preview,
    Heading,
    Row,
    Section,
    Text,
} from '@react-email/components';

interface VerificationEmailProps {
    username: string;
    otp: string;
}

export default function VerificationEmail({ username, otp }: VerificationEmailProps) {
    return (
        <Html lang="en" dir="ltr">
            <Head>
                <title>Verification Code</title>
                <Font
                    fontFamily="Roboto"
                    fallbackFontFamily="Verdana"
                    webFont={{
                        url: 'https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2',
                        format: 'woff2',
                    }}
                    fontWeight={400}
                    fontStyle="normal"
                />
            </Head>
            <Preview>Here&apos;s your verification code: {otp}</Preview>
            <Section>
                <Row>
                    <Heading as="h2">Hello {username},</Heading>
                </Row>
                <Row>
                    <Text>
                        Thank you for registering. Please use the following verification
                        code to complete your registration:
                    </Text>
                </Row>
                <Row>
                    <Text>{otp}</Text>
                </Row>
                <Row>
                    <Text>
                        If you did not request this code, please ignore this email.
                    </Text>
                </Row>
                {/* <Row>
            <Button
              href={`http://localhost:3000/verify/${username}`}
              style={{ color: '#61dafb' }}
            >
              Verify here
            </Button>
          </Row> */}
            </Section>
        </Html>
    );
}

Another Code Block:

import dbConnect from '@/lib/dbConnect';
import UserModel from '@/model/User';
import bcrypt from 'bcryptjs';
import { sendVerificationEmail } from '@/helpers/sendVerificationEmail';

export async function POST(request: Request) {
  await dbConnect();

  try {
    const { username, email, password } = await request.json();

    const existingVerifiedUserByUsername = await UserModel.findOne({
      username,
      isVerified: true,
    });

    if (existingVerifiedUserByUsername) {
      return Response.json(
        {
          success: false,
          message: 'Username is already taken',
        },
        { status: 400 }
      );
    }

    const existingUserByEmail = await UserModel.findOne({ email });
    const verifyCode = Math.floor(100000 + Math.random() * 900000).toString();

    if (existingUserByEmail) {
      if (existingUserByEmail.isVerified) {
        return Response.json(
          {
            success: false,
            message: 'User already exists with this email',
          },
          { status: 400 }
        );
      } else {
        const hashedPassword = await bcrypt.hash(password, 10);
        existingUserByEmail.password = hashedPassword;
        existingUserByEmail.verifyCode = verifyCode;
        existingUserByEmail.verifyCodeExpiry = new Date(Date.now() + 3600000);
        await existingUserByEmail.save();
      }
    } else {
      const hashedPassword = await bcrypt.hash(password, 10);
      const expiryDate = new Date();
      expiryDate.setHours(expiryDate.getHours() + 1);

      const newUser = new UserModel({
        username,
        email,
        password: hashedPassword,
        verifyCode,
        verifyCodeExpiry: expiryDate,
        isVerified: false,
        isAcceptingMessages: true,
        messages: [],
      });

      await newUser.save();
    }

    // Send verification email
    const emailResponse = await sendVerificationEmail(
      email,
      username,
      verifyCode
    );
    if (!emailResponse.success) {
      return Response.json(
        {
          success: false,
          message: emailResponse.message,
        },
        { status: 500 }
      );
    }

    return Response.json(
      {
        success: true,
        message: 'User registered successfully. Please verify your account.',
      },
      { status: 201 }
    );
  } catch (error) {
    console.error('Error registering user:', error);
    return Response.json(
      {
        success: false,
        message: 'Error registering user',
      },
      { status: 500 }
    );
  }
}

Dependencies: "@react-email/components": "0.0.7"

"@react-email/render": "^1.0.3"
"react-email": "^3.0.4"
"react-dom": "^19.0.0"
"react": "^19.0.0"

I tried updating the packages to the latest ones but it is not helping. On submitting the page was expected to redirect to the username's page

Upvotes: 0

Views: 22

Answers (1)

nikitimi
nikitimi

Reputation: 153

Regarding the section Code Using react-email:

Here is the sample output: enter image description here

I've created a minimal sample in my GitHub repository.

I've updated the package @react-email/components to latest: 0.0.31, removed parent Row component as NextJS is complaining about the hydration when using non table elements inside Row aka <tr>.

You can view the implementation of @react-email here ReactEmail.tsx, imported in server page component: verification/page.tsx added the Head/Title components from @react-email's title value as NextJS's MetaData

You cannot use Html and Head components inside components or pages as it is already set-upped by the layout.tsx, regarding the font Roboto, I've added it in line 5 of layout.tsx

You can learn more about NextJS directives here.

Upvotes: 0

Related Questions