如何从React将数据发送到Express

8
我正在尝试创建一款书籍应用程序,前端使用React,后端使用Node.js。当我尝试在后端创建时,它显示“Cannot POST /create”错误。我该怎么办?文件夹分为前端和后端两部分。我正在使用axios。作为React初学者,请帮帮我。如何将React表单中的数据传递到Express以保存?
this is the react component create

import React, {Component} from 'react';

class Create extends Component{
    render(){
        return(
            <div>
                <br/>
                <div class="container">
                    <form action="http://127.0.0.1:3000/create" method="post">
                        <div style={{width: '30%'}} class="form-group">
                            <input  type="text" class="form-control" name="BookID" placeholder="Book ID"/>
                        </div>
                        <br/>
                        <div style={{width: '30%'}} class="form-group">
                                <input  type="text" class="form-control" name="Title" placeholder="Book Title"/>
                        </div>
                        <br/>
                        <div style={{width: '30%'}} class="form-group">
                                <input  type="text" class="form-control" name="Author" placeholder="Book Author"/>
                        </div>
                        <br/>
                        <div style={{width: '30%'}}>
                            <button class="btn btn-success" type="submit">Create</button>
                        </div> 
                    </form>
                </div>
            </div>
        )
    }
}

export default Create;

这是后端的index.js文件

    var express = require('express');
    var app = express();
    var bodyParser = require('body-parser');
    var session = require('express-session');
    var cookieParser = require('cookie-parser');
    var cors = require('cors');
    app.set('view engine', 'ejs');

    //use cors to allow cross origin resource sharing
    app.use(cors({
        origin: 'http://localhost:3000',
        credentials: true
    }));




var books = [{
        "BookID": "1",
        "Title": "Book 1",
        "Author": "Author 1"
    },
    {
        "BookID": "2",
        "Title": "Book 2",
        "Author": "Author 2"
    },
    {
        "BookID": "3",
        "Title": "Book 3",
        "Author": "Author 3"
    }
]




app.get('/home', function (req, res) {
    console.log("Inside Home Login");
    res.writeHead(200, {
        'Content-Type': 'application/json'
    });
    console.log("Books : ", JSON.stringify(books));
    res.end(JSON.stringify(books));

})

app.post('/create', function (req, res) {
    var newBook = {
        "BookID": req.body.BookID,
        "Title": req.body.Title,
        "Author": req.body.Author
    }
    books.push(newBook)
    console.log(books);



})
//start your server on port 3001
app.listen(3001);
console.log("Server Listening on port 3001");

你发布的所有代码肯定不是在一个文件里吧? - Anurag Srivastava
是的,它不在同一个文件中。 - e.T55
理想情况下,您不应该有一个<form action="http://127.0.0.1:3000/create" method="post">,而是在表单提交时调用一个函数来进行POST请求。您能添加实际发起请求的axios代码吗? - Anurag Srivastava
类似于这样的内容 - https://dev59.com/i6vka4cB1Zd3GeqPy81T - Anurag Srivastava
3个回答

18

这里有一些错误。这是更新后的代码和出现问题的描述:

React App.js:

import React, { Component } from 'react';
import axios from 'axios';

class Create extends Component {
  constructor(props) {
    super(props);

    this.state = {
      bookID: '',
      bookTitle: '',
      bookAuthor: '',
    };
  }

  handleInputChange = e => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  };

  handleSubmit = e => {
    e.preventDefault();

    const { bookID, bookTitle, bookAuthor } = this.state;

    const book = {
      bookID,
      bookTitle,
      bookAuthor,
    };

    axios
      .post('http://localhost:3001/create', book)
      .then(() => console.log('Book Created'))
      .catch(err => {
        console.error(err);
      });
  };

  render() {
    return (
      <div>
        <br />
        <div className="container">
          <form onSubmit={this.handleSubmit}>
            <div style={{ width: '30%' }} className="form-group">
              <input
                type="text"
                className="form-control"
                name="bookID"
                placeholder="Book ID"
                onChange={this.handleInputChange}
              />
            </div>
            <br />
            <div style={{ width: '30%' }} className="form-group">
              <input
                type="text"
                className="form-control"
                name="bookTitle"
                placeholder="Book Title"
                onChange={this.handleInputChange}
              />
            </div>
            <br />
            <div style={{ width: '30%' }} className="form-group">
              <input
                type="text"
                className="form-control"
                name="bookAuthor"
                placeholder="Book Author"
                onChange={this.handleInputChange}
              />
            </div>
            <br />
            <div style={{ width: '30%' }}>
              <button className="btn btn-success" type="submit">
                Create
              </button>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

export default Create;
  1. 你因为使用了class而不是className而出现错误。class 是react.js中的保留字,不应该使用。
  2. 你正在使用默认的POST方法,我不建议这样做。我将POST拆分为自己的操作并使用常见的库axios进行CORS POST调用。我还创建了一个函数来处理在每次按键时输入更改的 react.js。
  3. 我向您的组件添加了state。 当有表单输入时将它们存储在state是很常见的。 我还更改了您变量的名称为Title Case,这是编写代码变量的常见方式。

Node.js index.js:

const express = require('express');
const logger = require('morgan');
const cors = require('cors');

const app = express();

//use cors to allow cross origin resource sharing
app.use(
  cors({
    origin: 'http://localhost:3000',
    credentials: true,
  })
);

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

let books = [];

app.get('/home', function(req, res) {
  console.log('Inside Home Login');
  res.writeHead(200, {
    'Content-Type': 'application/json',
  });
  console.log('Books : ', JSON.stringify(books));
  res.end(JSON.stringify(books));
});

app.post('/create', function(req, res) {
  const newBook = {
    BookID: req.body.bookID,
    Title: req.body.bookTitle,
    Author: req.body.bookAuthor,
  };

  books.push(newBook);
  console.log(books);
});

//start your server on port 3001
app.listen(3001, () => {
  console.log('Server Listening on port 3001');
});

  1. 你没有解析请求的主体,所以它返回为undefined。我添加了app.use(express.json());app.use(express.urlencoded({ extended: false }));这可以解决大部分问题。
  2. 我更新了req.body变量,以匹配从React传输过来的变量。
  3. 我添加了模块morgen,你在这里看到了app.use(logger('dev'));它可以帮助你显示所有请求和状态供开发人员使用。 在这种情况下,它显示你正在获得500(内部服务器错误),因为express无法读取未定义的bookID(因为主体未被解析)。

现在应该可以正常工作了,请告诉我是否有任何问题。


0

我不使用express,因此细节可能不适用。

本质上,您将需要向服务器发送网络请求。如何实现取决于您,最常见的方法是使用axios(一个库)或使用fetch api的vanilla js。

我只会使用fetch api。它需要两个参数:url和options。所以应该像这样调用fetch(url,options)。

因此,在您的情况下,它将是fetch('localhost:3001/create, options)。

选项中应该包含什么?我建议您查看fetch MDN文档https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

但在您的情况下,您需要传递一个带有method属性设置为post和要创建的新书籍的数据属性设置为书籍的JSON序列化对象的对象。

例如

let book ={
    BookId:1,
    Title: "coolBook",
    Author: "Me"
}

fetch("localhost:3001/create",
{
     method: "post",
     data: JSON.stringify(book)
}

当传递书籍时,如果传递的是字符串而不是对象,则可能需要在服务器上将该字符串解析为对象,以便您的表达/创建处理程序看起来更像:
app.post('/create', function (req, res) {
    var newBook = JSON.parse(req.body.data)
    books.push(newBook)
    console.log(books);
})

在React端,您需要创建一个事件处理程序来调用上面的fetch函数。我建议您观看React/Express教程,因为我无法在Stack Overflow问题中涵盖所有所需的内容,例如:在React中使用和验证表单、错误处理、异步/等待等。
祝一切顺利!希望这对您有所帮助。

你测试过你的代码吗? 我得到了这样的回复:无法发布 <! DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <title>错误</title> </head> <body> <pre>无法发布/ </ pre> </body> </html> - mfadel

0

你的/create端点应该有某种响应
例如:

app.post('/create', function (req, res) {
    var newBook = {
        "BookID": req.body.BookID,
        "Title": req.body.Title,
        "Author": req.body.Author
    }
    books.push(newBook)
    console.log(books);

   res.status(201).json({"some":"response"})


})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接