【问题标题】:Cast to ObjectId failed for value "undefined" at path "_id" for model "User"模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败
【发布时间】:2021-06-02 19:32:42
【问题描述】:

我已经被这个错误困扰了一段时间,我无法通过搜索 Stack 和 Google 来解决它。我有一个 ProfileScreen.js 来显示用户的个人资料。但是当您单击查看配置文件时,我收到此错误:Cast to ObjectId failed for value "undefined" at path "_id" for model "User"。从我所做的搜索中,我尝试将我的 Mongoose 版本回滚,但这并没有帮助。有人有什么想法吗?

userRouter.js

import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import bcrypt from 'bcryptjs';
import data from '../data.js';
import User from '../models/userModel.js';
import { generateToken } from '../utils.js';

const userRouter = express.Router();

userRouter.get('/seed', expressAsyncHandler(async (req, res) => {
  // await User.remove({});
  const createdUsers = await User.insertMany(data.users);
  res.send({ createdUsers });
}));

userRouter.post('/signin', expressAsyncHandler(async (req, res) => {
  const user = await User.findOne({ email: req.body.email });
  if(user) {
    if(bcrypt.compareSync(req.body.password, user.password)) {
      res.send({
        id: user._id,
        name: user.name,
        email: user.email,
        isAdmin: user.isAdmin,
        token: generateToken(user),
      });
      return;
    }
  }
  res.status(401).send({ message: 'Invalid email or password' });
}));

userRouter.post('/register', expressAsyncHandler(async(req, res) => {
  const user = new User({name: req.body.name, email: req.body.email,
    password: bcrypt.hashSync(req.body.password, 8),
  });
  const createdUser = await user.save();
  res.send({
    id: createdUser._id,
    name: createdUser.name,
    email: createdUser.email,
    isAdmin: createdUser.isAdmin,
    token: generateToken(createdUser),
  })
})
);

userRouter.get(
  '/:id',
  expressAsyncHandler(async (req, res) => {
    const user = await User.findById(req.params.id);
    if (user) {
      res.send(user);
    } else {
      res.status(404).send({ message: 'User Not Found' });
    }
  })
);

export default userRouter;

ProfileScreen.js

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { detailsUser } from '../actions/userActions';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';

export default function ProfileScreen() {
  const userSignin = useSelector((state) => state.userSignin);
  const { userInfo } = userSignin;
  const userDetails = useSelector((state) => state.userDetails);
  const { loading, error, user } = userDetails;
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(detailsUser(userInfo._id));
  }, [dispatch, userInfo._id]);
  const submitHandler = (e) => {
    e.preventDefault();
    // dispatch update profile
  };
  
  return (
    <div>
      <form className="form" onSubmit={submitHandler}>
        <div>
          <h1>User Profile</h1>
        </div>
        {loading ? (
          <LoadingBox></LoadingBox>
        ) : error ? (
          <MessageBox variant="danger">{error}</MessageBox>
        ) : (
          <>
            <div>
              <label htmlFor="name">Name</label>
              <input 
                id="name"
                type="text"
                placeholder="Enter name"
                value={user.name}>
                </input>
            </div>
            <div>
              <label htmlFor="email">Email</label>
              <input 
                id="email"
                type="email"
                placeholder="Enter email"
                value={user.email}
               >
                </input>
            </div>
            <div>
              <label htmlFor="password">Password</label>
              <input 
                id="password"
                type="password"
                placeholder="Enter password">
                </input>
            </div>
            <div>
              <label htmlFor="confirmPassword">Confirm Password</label>
              <input 
                id="confirmPassword"
                type="password"
                placeholder="Confirm password"
                >
                </input>
            </div>
            <div>
              <label/>
              <button className="primary" type="submit">Update Profile</button>
            </div>
          </>
          )}
      </form>
    </div>
  )
}

我搞砸了并发布了错误的代码,我发布了用户路由器代码而不是 ProfileScreen 代码。我已经添加了 ProfileScreen 代码。

提前感谢任何帮助。

-N8

【问题讨论】:

  • 我假设这是引发错误const user = await User.findById(req.params.id); 的行。您是否通过查看 Chrome 网络选项卡确认您实际上在请求正确的 URL?或者您从哪里发出网络请求?您的客户端代码是这里的主要嫌疑人。
  • 我编辑了我的问题以实际包含 ProfileScreen 的代码,我错误地发布了路由器代码。
  • 在你的useEffect 中,你能把这个console.log("User info", userInfo) 放在dispatch(detailsUser(userInfo._id)); 的正上方吗?然后检查控制台看看打印了什么?
  • 返回用户对象:
  • 用户信息{ID: “60408c4b912e51879c7c08c4”,名称: “马特·桑德斯”,邮件: “MShadows@A7X.com”,isAdmin:假的,令牌:“eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2M ... TU1fQ.PmUoyuJqj2cvnGVYkj21NcDP6BR3S1Ea7NOBg5-Arjs "}

标签: javascript node.js mongodb express mongoose


【解决方案1】:

问题似乎就在这里:

dispatch(detailsUser(userInfo._id));

根据您的用户对象,应该如下所示:

dispatch(detailsUser(userInfo.id));

由于_idundefined,因为它在对象中不存在,因此您最终发布到/undefined 而不是/60408c4b912e51879c7c08c4。因此出现错误。

【讨论】:

    【解决方案2】:

    当 mongoose 无法在此行上转换 req.params.id 时会出现此错误: const user = await User.findById(req.params.id); 到 ObjectId

    undefined 是不可转换的,无论如何你也找不到任何未定义为_id 的文档。 您可能想检查 req.params.id 是否未定义,然后根据它返回一些内容。

    请参阅here 以了解可转换的 objectId 是什么!

    【讨论】:

      猜你喜欢
      • 2021-07-04
      • 2021-07-17
      • 2020-07-31
      • 2018-03-17
      • 2023-03-28
      • 2021-06-05
      • 2021-03-13
      • 1970-01-01
      • 2017-05-23
      相关资源
      最近更新 更多