【问题标题】:Nodemon server with axios - Unable to Send带有 axios 的 Nodemon 服务器 - 无法发送
【发布时间】:2021-02-28 09:04:25
【问题描述】:

我有一个 React 应用程序,在这个应用程序中有一个名为 backend 的文件夹。此文件夹包含 2 个文件:

Config 通过 nodemailer 包含一个带有电子邮件和密码的变量。 Index.js(这是我的服务器应该运行的)有这个:

const path = require("path");
const express = require("express");
const transporter = require("./config");
const dotenv = require("dotenv");
dotenv.config();
const app = express();

const buildPath = path.join(__dirname, "..", "build");
app.use(express.json());
app.use(express.static(buildPath));

app.post("/send", (req, res) => {
  try {
    const mailOptions = {
      from: req.body.email, // sender address
      to: process.env.email, // list of receivers
      subject: req.body.subject, // Subject line
      html: `
      <p>You have a new contact request.</p>
      <h3>Contact Details</h3>
      <ul>
        <li>Name: ${req.body.name}</li>
        <li>Email: ${req.body.email}</li>
        <li>Subject: ${req.body.subject}</li>
        <li>Message: ${req.body.message}</li>
      </ul>
      `,
    };

    transporter.sendMail(mailOptions, function (err, info) {
      if (err) {
        res.status(500).send({
          success: false,
          message: "Something went wrong. Try again later",
        });
      } else {
        res.send({
          success: true,
          message: "Thanks for contacting us. We will get back to you shortly",
        });
      }
    });
  } catch (error) {
    res.status(500).send({
      success: false,
      message: "Something went wrong. Try again later",
    });
  }
});

app.listen(3030, () => {
  console.log("server start on port 3030");
});

然后,在不同的文件夹(组件)中,我有一个获取表单信息的组件文件,它应该将它带到服务器:

import React, { useState } from "react";
import axios from "axios";
import { Form, Button } from "react-bootstrap";
import Navbar from "../components/Navbar";
import BottomNav from "../components/BottomNav";

const Contact = () => {
  const [state, setState] = useState({
    name: "",
    email: "",
    subject: "",
    message: "",
  });

  const [result, setResult] = useState(null);

  const sendEmail = event => {
    event.preventDefault();
    axios
      .post("/send", { ...state })
      .then(response => {
        setResult(response.data);
        setState({
          name: "",
          email: "",
          subject: "",
          message: "",
        });
      })
      .catch(() => {
        setResult({
          success: false,
          message: "Something went wrong. Try again later",
        });
      });
  };

  const onInputChange = event => {
    const { name, value } = event.target;

    setState({
      ...state,
      [name]: value,
    });
  };

  return (
    <div>
      <Navbar />
      {result && (
        <p className={`${result.success ? "success" : "error"}`}>
          {result.message}
        </p>
      )}
      <form
        className="phs-form-wrapper mt-8 h-screen flex flex-col items-center "
        onSubmit={sendEmail}
      >
        <Form.Group
          className=" phs-form-group flex flex-col items-center"
          controlId="name"
        >
          <Form.Label className="phs-form-label mr-2">Full Name</Form.Label>
          <Form.Control
            type="text"
            name="name"
            value={state.name}
            onChange={onInputChange}
          />
        </Form.Group>
        <Form.Group
          className=" phs-form-group flex flex-col items-center"
          controlId="email"
        >
          <Form.Label className="phs-form-label mr-2">Email</Form.Label>
          <Form.Control
            type="text"
            name="email"
            value={state.email}
            onChange={onInputChange}
          />
        </Form.Group>
        <Form.Group
          className=" phs-form-group flex flex-col items-center"
          controlId="subject"
        >
          <Form.Label className="phs-form-label mr-2">Subject</Form.Label>
          <Form.Control
            type="text"
            name="subject"
            value={state.subject}
            onChange={onInputChange}
          />
        </Form.Group>
        <Form.Group
          className=" phs-form-group flex flex-col items-center"
          controlId="subject"
        >
          <Form.Label className="phs-form-label mr-2">Message</Form.Label>
          <Form.Control
            as="textarea"
            name="message"
            value={state.message}
            rows="3"
            onChange={onInputChange}
          />
        </Form.Group>
        <Button
          className="phs-form-submit-button bg-black text-white p-4 mt-4"
          variant="primary"
          type="submit"
        >
          Submit
        </Button>
      </form>
      <BottomNav />
    </div>
  );
};

export default Contact;

我在两台服务器上都收到错误消息。 在 localhost:3000 上,每当我尝试提交我得到的信息时,我都会在其中运行我的 react 应用程序:

VM635:1 POST http://localhost:3000/send 404 (Not Found)

在本地主机上:3030:

GET http://localhost:3030/ 404 (Not Found)
localhost/:1 Refused to load the image 'http://localhost:3030/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

我注意到我的 axios 有一个 .post("/send") 但我尝试将其更改为 localhost:3030/send 并且也不起作用。

另外,我有 2 个 package.json 文件,一个在我的 react 文件夹 (web) 中,另一个在我的后端文件夹中。

后端有一个这样的脚本:

"scripts": {
    "dev": "nodemon src/index.js"
  }

网页版有不同的脚本,所以我运行不同的服务器:

"scripts": {
    "start": "npm run watch:css && react-scripts start",
    "build": "npm run watch:css && react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "watch:css": "postcss src/assets/tailwind.css -o src/assets/main.css"
  }

有什么想法吗?

【问题讨论】:

    标签: node.js reactjs server nodemailer nodemon


    【解决方案1】:

    当您在不同端口(本例中为:3000 和 :3030)上同时运行后端和前端服务器时,您需要在 axios 调用中特别提及整个 url。在这种情况下,/send 被认为是 http://localhost:3000,其中 POST 方法不存在(你得到 404 的原因)。您必须进行以下 axios 调用:

    const sendEmail = event => {
        event.preventDefault();
        axios
          .post("http://localhost:3030/send", state, {
            headers: { 
             'Access-Control-Allow-Origin' : '*'
            },
          })
          .then(response => {
            ...
          })
          .catch(() => {
            ...
          });
      };
    

    您也不需要在 axios 调用中传播状态。原因是 axios 调用接受第二个参数作为对象。

    【讨论】:

    • 我在发帖之前尝试过这个并给了我以下错误::3000/contact:1 Access to XMLHttpRequest at 'http://localhost:3030/send' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    • 另外,我确实安装了“允许 CORS”chrome 扩展
    • 这是您的原始错误。 Soln:将 axios.post 中的第三个参数传递为:{ headers: { 'Access-Control-Allow-Origin' : '*', } }
    【解决方案2】:

    在您的 react 应用程序上尝试将其发送到“http://localhost:3030/send”而不是“/send”。 我相信这是因为您的服务器 URL 和您的反应开发服务器 URL 在本地运行时是不同的

    【讨论】:

      猜你喜欢
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 2019-11-20
      • 2022-08-14
      • 2017-10-05
      相关资源
      最近更新 更多