I'm trying to use the SendGrid module in my React application to send an email using a contact form. However, when I run npm start, I encounter the following error:
Failed to compile.
Module not found: Error: Can't resolve 'fs' in '.../node_modules/@sendgrid/helpers/classes'
The error message suggests that the 'fs' and 'path' modules cannot be resolved in the @sendgrid/helpers/classes/attachment.js file.
I also receive the warning:
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
Here is my project structure: card.tsx (React component for the contact form):
import React, { useState, useEffect, useRef } from "react";
import cardcss from "./Card.module.css";
interface CardProps {
imageUrl: string;
title: string;
body: string;
onSubmitForm: (contactData: {
Name: string;
Email: string;
Message: string;
}) => void;
}
function Card(props: CardProps) {
const [message, setMessage] = useState("");
const messageInputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (messageInputRef.current) {
messageInputRef.current.focus();
messageInputRef.current.setSelectionRange(0, 0);
// Delay setting the cursor position
setTimeout(() => {
messageInputRef.current?.setSelectionRange(0, 0);
}, 0);
}
}, []);
const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
event.target.setSelectionRange(0, 0);
};
function ContactForm() {
const nameInputRef = useRef<HTMLInputElement>(null);
const emailInputRef = useRef<HTMLInputElement>(null);
const messageInputRef = useRef<HTMLInputElement>(null);
const submitRef = useRef<HTMLButtonElement>(null);
function submitHandler(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
if (
nameInputRef.current &&
emailInputRef.current &&
messageInputRef.current
) {
const nameInput = nameInputRef.current.value;
const emailInput = emailInputRef.current.value;
const messageInput = messageInputRef.current.value;
const contactData = {
Name: nameInput,
Email: emailInput,
Message: messageInput,
};
if (submitRef.current) {
const submittedButton = submitRef.current.value;
const contactDataWithButton = {
...contactData,
submitbutton: submittedButton,
};
// Do something with contactDataWithButton
props.onSubmitForm(contactData);
}
}
}
return (
<div className={cardcss.cardcontainer}>
<div className={cardcss.imagecontainer}>
<img src={props.imageUrl} alt="" />
</div>
<div className={cardcss.cardtitle}>
<h3>{props.title}</h3>
</div>
<div className={cardcss.cardbody}>
<p>{props.body}</p>
<form onSubmit={submitHandler}>
<div>
<label className={cardcss.namelabel} htmlFor="name">
Name:
</label>
<input
className={cardcss.nameinput}
type="text"
id="name"
name="name"
ref={nameInputRef}
/>
</div>
<div className={cardcss.emailcontainer}>
<label className={cardcss.emaillabel} htmlFor="email">
Email:
</label>
<input
className={cardcss.emailinput}
type="text"
id="email"
name="email"
ref={emailInputRef}
/>
</div>
<div className={cardcss.messagecontainer}>
<label className={cardcss.messagelabel} htmlFor="message">
Message:
</label>
<input
ref={messageInputRef}
className={cardcss.messageinput}
type="text"
id="message"
name="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
onFocus={handleFocus}
/>
<button className={cardcss.sendbutton} ref={submitRef}>
Send
</button>
</div>
</form>
</div>
</div>
);
}
return <ContactForm />;
}
export default Card;
contact.tsx(React component that uses the Card component):
import React, { useRef } from "react";
import contactcss from "./Contact.module.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Card from "../../components/ui/Card";
import {
faInstagram,
faFacebook,
faLinkedin,
faDiscord,
} from "@fortawesome/free-brands-svg-icons";
import emaillogo from "../../resources/email-logo.png";
import { setApiKey, send } from "@sendgrid/mail";
const Contact: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.setSelectionRange(0, 0);
}
};
setApiKey(
"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"
);
function submitFormHandler(contactData: {
Name: string;
Email: string;
Message: string;
}) {
const { Name, Email, Message } = contactData;
const msg = {
to: "paristiffany12@gmail.com",
from: Email,
subject: "GDSC Contact Form - New Message",
text: `Message from: ${Name}\nMessage: ${Message}`,
html: `<p>Message from: ${Name}</p><p>Message: ${Message}</p>`,
};
send(msg)
.then(() => {
console.log("Email sent successfully");
})
.catch((error) => {
console.error(error.toString());
});
}
return (
<div>
<div>
<div className={contactcss.background}>
<img
className={contactcss.emaillogo}
src={emaillogo}
alt="Contact Us"
/>
<div className={contactcss.contact}>Contact Us</div>
</div>
</div>
<Card
title="We're keen to hear from you!"
imageUrl="https://images.app.goo.gl/D6m6hHMnP1gjsKKV7"
body=""
onSubmitForm={submitFormHandler}
/>
<div className={contactcss.whitebackground}>
<div className={contactcss.socials}>
<h1>Follow Our Socials</h1>
<p className={contactcss.socialmedia}>
Stay connected with GDSC USYD by following us on our social media
channels:
</p>
<div>
<a href="https://www.instagram.com/gdscusyd/">
<FontAwesomeIcon
className={contactcss.instagram}
icon={faInstagram}
/>
</a>
<a href="https://www.facebook.com/gdsc.usyd">
<FontAwesomeIcon
className={contactcss.facebook}
icon={faFacebook}
/>
</a>
<a href="https://discord.com/channels/872033047652990986/872033047652990989">
<FontAwesomeIcon
className={contactcss.discord}
icon={faDiscord}
/>
</a>
<a href="https://www.linkedin.com/company/gdsc-usyd/">
<FontAwesomeIcon
className={contactcss.linkedin}
icon={faLinkedin}
/>
</a>
</div>
</div>
</div>
</div>
);
};
export default Contact;
indexfirebase.js (Node.js file to handle sending emails):
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var express_1 = require("express");
var mail_1 = require("@sendgrid/mail");
var path_browserify_1 = require("path-browserify");
// Set up SendGrid API key
mail_1.default.setApiKey("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");
// Create Express app
var app = (0, express_1.default)();
// Middleware to parse JSON requests
app.use(express_1.default.json());
// Route to handle sending emails
app.post("/send-email", function (req, res) {
var _a = req.body, Name = _a.Name, Email = _a.Email, Message = _a.Message, submitbutton = _a.submitbutton;
var msg = {
to: "paristiffany12@gmail.com",
from: "gdscusyd@gmail.com",
subject: "Example Subject",
text: "Name: ".concat(Name, "\nEmail: ").concat(Email, "\nMessage: ").concat(Message, "\nSubmit Button: ").concat(submitbutton),
html: "<p>Name: ".concat(Name, "</p><p>Email: ").concat(Email, "</p><p>Message: ").concat(Message, "</p><p>Submit Button: ").concat(submitbutton, "</p>"),
};
mail_1.default
.send(msg)
.then(function () {
res.status(200).json({ message: "Email sent successfully" });
})
.catch(function (error) {
console.error(error.toString());
res.status(500).json({ error: "Failed to send email" });
});
});
// Set up fallback for path module
path_browserify_1.resolve.fallback = { path: path_browserify_1.require.resolve("path-browserify") };
// Start the server
app.listen(3000, function () {
console.log("Server started on port 3000");
});
I believe this error is occurring because the fs and path modules are part of the Node.js environment and are not available in a browser environment.
My questions are:
- Can I use the SendGrid module in a browser-based React application?
- Is it possible to fix this error and make the SendGrid module work in my React application?
- If it's not possible, what alternatives can I use to send emails from a contact form in a React application?
I appreciate any help or guidance to resolve this issue. Thank you in advance!