首页 > 解决方案 > 使用 MERN 向 Mongo 插入数据只存储 ID

问题描述

我刚刚开始使用 MERN,目前正在努力理解为什么 MongoDB 会存储除了生成 ID 之外的任何内容。虽然 API 的状态码在运行应用程序时显示为 200,但数据库存储如下内容:

{
    "_id":{"$oid":"613c98f76daf3b1d94cbbe6b"},
    "firstName":null,
    "lastName":null,
    "email":null
}

前端和后端的代码如下:

从中进行 API 调用的 React 组件

export default class TableScreen extends React.Component {
    state = {
        firstName: '',
        lastName: '',
        email: '',
        isVisible: false,
        position: "centre"
    }

    openDialog = () => {
        this.setState((state, props) => ({
            isVisible: true
        }))
    }

    closeDialog = () => {
        this.setState((state, props) => ({
            isVisible: false
        }))
    }

    onChangeFirstName = (e) => {
        this.setState({
            firstName : e.target.value
        })
    }

    onChangeLastName = (e) => {
        this.setState({
            lastName : e.target.value
        })
    }

    onChangeEmail = (e) => {
        this.setState({
            email : e.target.value
        })
    }

    addUser = () => {     //This is the api call
        const requestOption = {
            method: 'POST',
            body: JSON.stringify(this.state.firstName, this.state.lastName, this.state.email)
        }
        fetch("http://localhost:3001/api/add", requestOption)
            .then(res => res.json())
            .then(data => console.log(data))
    }

    render() {
        return (
            <div>
                <Button variant="outlined" color="primary" onClick={() => this.openDialog()}>
                    Add
                </Button>
                {/* <UserList></UserList> */}
                <Dialog open={this.state.isVisible} onClose={() => this.closeDialog()} aria-labelledby="form-dialog-title">
                    <DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
                    <DialogContent>
                        <DialogContentText>
                            To subscribe to this website, please enter your email address here. We will send updates
                            occasionally.
                        </DialogContentText>
                        <TextField
                            autoFocus
                            margin="dense"
                            id="firstName"
                            label="First name"
                            type="email"
                            fullWidth
                            onChange={this.onChangeFirstName}
                        />
                        <TextField
                            margin="dense"
                            id="lastName"
                            label="Last name"
                            type="email"
                            fullWidth
                            onChange={this.onChangeLastName}
                        />
                        <TextField
                            margin="dense"
                            id="email"
                            label="Email"
                            type="email"
                            fullWidth
                            onChange={this.onChangeEmail}
                        />
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={() => this.closeDialog()} color="primary">
                            Cancel
                        </Button>
                        //The button that invokes the API
                        <Button onClick={() => this.addUser()} color="primary"> 
                            Add
                        </Button>
                    </DialogActions>
                </Dialog>
            </div>
        );
    }
}

后端:

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    
    const mongoDb = require('mongodb');
    
    const MongoClient = mongoDb.MongoClient;
    
    const uri = "mongodb+srv://coolhack069:XzC6N7dOyUeQl8M9@cluster0.kz6v9.mongodb.net/crud?retryWrites=true&w=majority";
    const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
    
    app.use(cors());
    
    app.use(express.json());
    
    const port = 3001;
    
    app.post('/api/add', (req, res) => {
        console.log(req);
    
        // const user = req.body;
        const fName = req.body.firstName;
        const lName = req.body.lastName;
        const email = req.body.email;
    
        client.connect(err => {
            if(err) {
                throw err;
            }
            
                const collection = client.db('crud').collection('data');
                // const storeData = user;
                const storeData = {"firstName" : fName, "lastName" : lName, "email" : email};
                collection.insertOne(storeData, function(err, result) {
                    res.send(result);
                    client.close();
                });
            })
        });
app.listen(port, () => {
   console.log(`Application listening at http://localhost:${port}`) 
});

package.json档案_

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "mongodb": "^4.1.1",
    "mongoose": "^6.0.5"
  }
}

标签: node.jsreactjsmongodbexpress

解决方案


问题在于TableScreen组件中的 API 函数。我在 addUser 方法中修改了 requestOption 对象,方法是添加 aheader并更改bodya 位。代码片段如下:

addUser = () => {     //This is the api call
        const requestOption = {
            method: 'POST',
            headers : {'Content-Type' : 'application/json'},
            body: JSON.stringify({firstName: this.state.firstName, lastName : this.state.lastName, email: this.state.email})
        }
        fetch("http://localhost:3002/api/add", requestOption)
            .then(res => res.json())
            .then(data => console.log(data))
    }

我刚刚意识到我已经定义了后端来处理 JSON 中的数据。app.use(express.json());是执行此操作的行。因此,后端将期望接收我们希望以相同格式存储的任何数据。因此,我们需要做的第一件事是确保发送的数据采用相同的格式,我们通过定义 headers 键来做到这一点,该键基本上是为了暗示后端它将接收的内容将是 JSON . 然后body定义密钥以对象格式发送数据。如果您在问题的初始代码中检查这一行,该JSON.stringify方法看起来body: JSON.stringify(this.state.firstName, this.state.lastName, this.state.email)是错误的,因为我们没有以后端期望的格式发送数据。所以简单的解决方法是this.state.firstName, this.state.lastName, this.state.email在一对大括号中添加这一行{}将其转换为对象,如上面修改后的代码段所示。如果听起来不正确,我会邀请其他人编辑此答案。

PS:这对于 POST 和 PUT 请求都是理想的


推荐阅读