I made a feedback form, the client server is working well separately. But when they were combined on the same host when you click send (request feedback by mail ) an error is coming out. Swears at the line in Hero.jsx const response = await fetch("/api/feedback", {
backend server.js
const express = require('express');
const nodemailer = require('nodemailer');
const server = express();
server.use(express.static(__dirname + '/public'));
server.use(express.json());
server.get('/', (req, res) => {
res.sendFile("public/index.html", { root: __dirname})
})
server.post("/api/feedback", async(req, res) => {
try {
const transporter = nodemailer.createTransport({
host: "smtp.mail.ru",
port: 465,
secure: true,
auth: {
user: "[email protected]",
pass: "**********"
}
});
const { name, phone, message} = req.body;
await transporter.sendMail({
from: "[email protected]",
to: "[email protected]",
subject: "Тема письма",
text: `${name} ${phone} ${message}`,
html:
`
<p>${name}</p>
<p>${phone}</p>
<p>${message}</p>
`
});
return res.status(200).send({
status: 200,
message: 'Успешня отправка'
})
} catch (e) {
return res.status(500).send({
status:500,
message: 'Ошибка при запросе'
});
}
})
server.listen(5000, () => {
console.log('listening on port 5000');
})
script.js
const FEEDBACK_FORM = document.querySelector('#feedback-form');
function sendFeedback(feedback) {
fetch("/api/feedback" , {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(feedback),
}).then((response)=>response.json()).then(data => {
console.log(data);
alert('Успешно');
}).catch((error) => {
console.error(error);
alert('Ошибка');
});
}
FEEDBACK_FORM.addEventListener('submit', (e) => {
e.preventDefault();
const feedbackFormData = new FormData(e.target);
console.log('feedbackFormData', feedbackFormData);
const feedback = Object.fromEntries(feedbackFormData);
console.log('feedback', feedback);
sendFeedback(feedback);
})
Front Hero.jsx
import React, { useState } from "react";
import styles from "./Hero.module.css";
import { getImageUrl } from "../../utils";
export const Hero = () => {
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState({
name: "",
phone: "",
message: ""
});
const openModal = () => {
setIsOpen(true);
};
const closeModal = () => {
setIsOpen(false);
};
const handleCall = () => {
window.location.href = "tel:**************";
};
const handleFormSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch("/api/feedback", {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(formData),
});
if (response.ok) {
alert('Успешно');
setFormData({
name: "",
phone: "",
message: ""
});
} else {
alert('Ошибка');
}
} catch (error) {
console.error(error);
alert('Ошибка');
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prevData) => ({
...prevData,
[name]: value
}));
};
return (
<section className={styles.container}>
<div className={styles.content}>
<h1 className={styles.title}>*********</h1>
<p className={styles.description}>
«Ya»
</p>
<a href="tel:+**********" className={styles.contactBtn} onClick={handleCall}>
Позвонить
</a>
<button onClick={openModal} className={styles.contactBTN}>
Оставить заявку
</button>
{isOpen && (
<form onSubmit={handleFormSubmit}>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Имя"
/>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
placeholder="Телефон"
/>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Сообщение"
/>
<button type="submit">Отправить</button>
</form>
)}
</div>
<img
src={getImageUrl("hero/heroImage.png")}
alt="Hero image of me"
className={styles.heroImg}
/>
<div className={styles.topBlur} />
<div className={styles.bottomBlur} />
</section>
);
};
export default Hero;
I tried a lot of things To help solve the problem
2
Did you make a proxy setup for React application? It looks like proxy problem. When you make requests from JavaScript, there are two ways.
- Use absolute URL like
fetch("http://localhost:8080/api/feedback", ...)
- Use relative URL like
fetch("/api/feedback", ...)
what you did
When you use absolute path, this request is sent to backend directly from browser. In this case, you should setup CORS policy for your backend application because your frontend dev server and backend server have different origins.
When you use relative path, this request is sent to frontend server which is setup on your browser address window. In this case, you need to use proxy.
Setup a proxy for dev server, this is different depending on your bundler.
- CRA(Webpack) – setup proxy configuration in package.json
- Vite – setup proxy configuration in vite.config.ts