尝试更新MERN堆栈中User模式内的属性,但难以将数据发送到MongoDB

xzlaal3s  于 2023-01-25  发布在  Go
关注(0)|答案(1)|浏览(68)

目前,我的考点如下:首先,用户可以注册一个帐户,之后他们将能够更新他们的配置文件,因为在注册时,他们输入的所有内容都是他们的电子邮件和密码,所以他们的name属性仍然是一个空字符串。
我的用户模型:

const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
    email: {type: String, required: true},
    passwordHash: {type:String, required: true},
    firstName: {type:String, default:""},
});

const User = mongoose.model("user", userSchema);

module.exports = User;

其他东西,如姓氏,地址,生物等将很容易添加,一旦我弄清楚这个问题。
注册后,用户将可以访问一个简单的表单,该表单允许他们输入一个名称来创建一个配置文件(目前,只有名字)。
我用作React组件的CreateProfile.js文件如下所示:

import React, { useContext, useState } from "react";
import axios from "axios";
import AuthContext from "../context/AuthContext";
import { useNavigate } from "react-router-dom";

function CreateProfile() {

    const [firstName, setFirstName] = useState("");

    const {getLoggedIn} = useContext(AuthContext);
    const navigate = useNavigate();

    async function createProfile(e) {
        e.preventDefault();

        try {
            const profileData = {
                firstName,
            };
            console.log(profileData)
            await axios.post("http://localhost:5000/auth/createProfile", profileData);
            await getLoggedIn();
            navigate("/");
        } catch (error) {
            console.error(error);
        }
    }
    

    return (
        <div>
            <h1>Create your profile</h1>
            <form onSubmit={createProfile}>
                <input type="text" 
                placeholder="First Name"
                onChange={(e) => setFirstName(e.target.value)}
                value={firstName} 
                />
                <button type="submit">Create Profile</button>
            </form>
        </div>
    );
}

export default CreateProfile;

当点击"创建配置文件"按钮时,你会通过navigate("/")自动重定向回临时的"主页",navigate("/")功能目前工作正常,profileData被发送到userRouter,相关代码如下:

router.post("/createProfile", async (req,res) => {
    try {
        const updatedUser = await User.findOneAndUpdate(
            { $set: {firstName: req.body.firstName} },
            { new: false }
        );
        res.json(updatedUser);
    } catch (error) {
        console.error(error);
        res.status(500).send();
    }
});

为了确保我正确地处理了路由设置,下面是我的服务器端index.js:

const express = require("express");
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const cookieParser = require("cookie-parser");
const cors = require("cors");

dotenv.config();

//set up server

const app = express();

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port: ${PORT}`));

app.use(express.json());
app.use(cookieParser());
app.use(cors({
    origin: ["http://localhost:3000"],
    credentials: true,
}));

//remove the warning
mongoose.set('strictQuery', true)

//connect to mongoDB
mongoose.connect(process.env.MDB_CONNECT, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
}, (err) => {
    if (err) return console.error(err);
    console.log("Connected to MongoDB");
});

// set up routes
app.use("/auth", require("./routers/userRouter"));

还有一个,这里是前端AuthContext.js,用于检查用户是否登录:

import React, { createContext, useEffect, useState } from "react";
import axios from "axios";

const AuthContext = createContext();

function AuthContextProvider(props) {
    const [loggedIn, setLoggedIn] = useState(undefined);

    async function getLoggedIn() {
        const loggedInRes = await axios.get("http://localhost:5000/auth/loggedIn");
        setLoggedIn(loggedInRes.data);
    }

    useEffect(() => {
        getLoggedIn();
    }, []);

    return <AuthContext.Provider value={{loggedIn, getLoggedIn}}>
        {props.children}
    </AuthContext.Provider>;
};

export default AuthContext;
export {AuthContextProvider};

我做错了什么,使得MongoDB无法获取更新后的firstName?当我在表单中输入"test"并点击提交按钮时,对象确实被创建了,但并没有进入MongoDB。我应该怎么做呢?问题出在userRouter还是其他地方?

我一直在网上寻找以前问过类似的问题,并尝试了一些不同的东西在我的userRouter.js文件,在我结束之前,我目前有(这仍然不工作),无济于事.尝试1:

router.post("/createProfile", async (req,res) => {
    var _id = req.body._id;
    console.log(_id);
    var profile = {
        firstName: req.body.firstName,
    }
    

    User.findByIdAndUpdate(_id, req.body.firstName, {new:false}, function(
        err,
        profile
    ) {
        if (err) {
            console.log("err", err);
            res.status(500).send(err);
        } else {
            console.log("success");
            console.log(profile);
            console.log(_id);
            console.log(req.body.email);
            res.send(profile);
        }
    });
});

我也尝试过用res.send(req.body.firstName)来代替,这很愚蠢,显然不起作用(如果你还不知道,我是新手)。
我也试过:

try {
        const profile = await User.create(req.body);
        console.log("success");
        res.send(profile);
    } catch (error) {
        console.log(req.body);
        console.log("err", error);
        res.status(500).send(error);
    }

但显然没有成功。
最后

try {
        const {firstName} = req.body;
        const test = User.updateOne(firstName);
        res.send(test);
    } catch (error) {
        console.error(error);
        res.status(500).send();
    }

从其他答案中,我看到人们会做res.json()或res.send()或res.put(),但我不确定在我的情况下应该做哪一个,尽管我怀疑这是我的问题的根本原因。
我很感激任何帮助,如果你需要任何额外的上下文或代码,我会相应地编辑我的帖子。我的注册/登录/注销的东西工作正常,我只是不能为我的生活似乎创建注册后的个人资料创建功能正确。

zwghvu4y

zwghvu4y1#

要更新之前创建的文档,您需要在路径的主体或路径参数中添加_id,因此您需要在前端添加一些逻辑来检索登录用户的ID。

import mongoose from 'mongoose';

router.post('/createProfile', async (req, res) => {
  const {_id, firstName} = req.body;
  try {
    const updatedUser = await User.findByIdAndUpdate(
      _id,
      {firstName: firstName},
      {new: true}, // "new: true" or "returnOriginal: false"
    );
    res.status(200).json(updatedUser);
  } catch (error) {
    // ...
  }
});

函数findByIdAndUpdate需要id、新值和可选的选项对象(https://mongoosejs.com/docs/api.html#model_Model-findByIdAndUpdate)。“您应该将新选项设置为true以在应用更新后返回文档”。
您也可以使用findOneAndUpdate执行此操作:

const updatedUser = await User.findOneAndUpdate(
  {_id: new mongoose.Types.ObjectId(req.body._id)},
  {$set: {firstName: req.body.firstName}},
  {new: true}
);

相关问题