CastError:模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败

Posted

技术标签:

【中文标题】CastError:模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败【英文标题】:CastError: Cast to ObjectId failed for value "undefined" at path "_id" for model "User" 【发布时间】:2021-07-04 15:46:42 【问题描述】:

我尝试在用户登录帐户后在登录屏幕中接收用户数据。登录帐户一切正常,但未显示来自用户的任何数据。我搜索这种类型的错误并尝试更改代码中的一些内容,甚至添加了mongoose.Types.ObjectId("user id"),但不起作用。

这是我的用户模型:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema(
    name: 
        type: String,
        required: true,
    ,
    email: 
        type: String,
        required: true,
    ,
    passwordHash: 
        type: String,
        required: true,
    ,
    phone: 
        type: String,
        required: true,
    ,
    isAdmin: 
        type: Boolean,
        default: false,
    ,
    street: 
        type: String,
        default: ''
    ,
    apartment: 
        type: String,
        default: ''
    ,
    zip :
        type: String,
        default: ''
    ,
    city: 
        type: String,
        default: ''
    ,
    country: 
        type: String,
        default: ''
    

);

userSchema.virtual('id').get(function () 
    return this._id.toHexString();
);

userSchema.set('toJSON', 
    virtuals: true,
);

exports.User = mongoose.model('User', userSchema);
exports.userSchema = userSchema;

这是我用来从后端调用我的 POST 和 GET 方法的脚本的 auth actions.js 部分:

export const loginUser = (user, dispatch) => 
    fetch(`$baseURLusers/login`, 
        method: "POST",
        body: JSON.stringify(user),
        headers: 
            Accept: "application/json",
            "Content-Type": "application/json",
        ,
    )
    .then((res) => res.json())
    .then((data) => 
        if (data) 
            const token = data.token;
            AsyncStorage.setItem("jwt", token)
            const decoded = jwt_decode(token)
            dispatch(setCurrentUser(decoded, user))
         else 
           logoutUser(dispatch)
        
    )
    .catch((err) => 
        Toast.show(
            topOffset: 60,
            type: "error",
            text1: "Please provide correct credentials",
            text2: ""
        );
        logoutUser(dispatch)
    );
;

export const getUserProfile = (id) => 
    fetch(`$baseURLusers/$id`, 
        method: "GET",
        body: JSON.stringify(user),
        headers: 
            Accept: "application/json",
            "Content-Type": "application/json"
        ,
    )
    .then((res) => res.json())
    .then((data) => console.log(data));

这是用户的路由,用于 GET 方法:

router.get(`/`, async (req, res) =>
    const userList = await User.find().select('-passwordHash');

    if(!userList) 
        res.status(500).json(success: false)
     
    res.send(userList);
)

router.get('/:id', async(req,res)=>
    const user = await User.findById(req.params.id).select('-passwordHash');

    if(!user) 
        res.status(500).json(message: 'The user with the given ID was not found.')
     
    res.status(200).send(user);
)

这是我要填充的屏幕:

import React, useContext, useState, useCallback from 'react';
import  View, Text, ScrollView, Button, StyleSheet  from 'react-native';
import  Container  from 'native-base'
import  useFocusEffect  from "@react-navigation/native"
import AsyncStorage from "@react-native-community/async-storage"

import axios from "axios"
import baseURL from "../../assets/common/baseUrl"

import AuthGlobal from "../../Context/store/AuthGlobal"
import  logoutUser  from "../../Context/actions/Auth.actions"
import  useEffect  from 'react/cjs/react.development';

const UserProfile = (props) => 
    const context = useContext(AuthGlobal)
    const [userProfile, setUserProfile] = useState()

    useEffect(() => 
        if(
            context.stateUser.isAuthenticated === false ||
            context.stateUser.isAuthenticated === null
        ) 
            props.navigation.navigate("Login")
        

        AsyncStorage.getItem("jwt")
        .then((res) => 
            axios
                .get(`$baseURLusers/$context.stateUser.user.sub`, 
                    headers:  Authorization: `Bearar $res` ,
                )
                .then((user) => setUserProfile(user.data))
        )
        .catch((error) => console.log(error))

    return () => 
        setUserProfile();
    

    , [context.stateUser.isAuthenticated])
    return(
        <Container>
            <ScrollView>
                <Text style= fontSize: 30>
                    userProfile ? userProfile.name : ""
                </Text>
                <View style=marginTop: 20>
                    <Text style=margin: 10>
                        Email: userProfile ? userProfile.email : ""
                    </Text>
                    <Text style=margin: 10>
                        Phone: userProfile ? userProfile.phone : ""
                    </Text>
                </View>
                <View style= marginTop: 80 >
                    <Button title="Sign Out" onPress=() => [
                        AsyncStorage.removeItem("jwt"),
                        logoutUser(context.dispatch)
                    ]/>
                </View>
            </ScrollView>
        </Container>
    )


export default UserProfile;

这是我的用户屏幕的 ss:

【问题讨论】:

正如猫鼬所说,它不能将 undefined 的值转换为 ObjectId,我认为您不会在前端向 API 发送值。如果提供了 id 参数,您能否仔细检查请求(通过 console.log(req.params.id)? 前段时间检查过,一切正常,用户ID看起来不错,没有多余的空格或一些字符。 根据错误消息,您在 req.params.id 中提供的值未定义。如果已填充,您可以尝试通过 mongoose.Types.ObjectId 创建一个新的 ObjectId。所以像这样的 User.findById(new ObjectId(req.params.id) 【参考方案1】:

我前段时间解决了,但我忘了发布答案。 问题是当我尝试解析我的用户 ID 的参数时。所以我创建了另一个变量,并将包含用户 ID 的旧“子”变量保存在现在的变量“userID”中,这样​​我就可以正常工作了。

这是新的 UserProfile.js 脚本:

import React, useContext, useState, useEffect, useCallback from 'react';
import  View, Text, ScrollView, Button, StyleSheet  from 'react-native';
import  Container  from 'native-base'
import  useFocusEffect  from "@react-navigation/native"
import AsyncStorage from "@react-native-community/async-storage"
import OrderCard from "../../Shared/OrderCard"

import axios from "axios"
import baseURL from "../../assets/common/baseUrl"

import AuthGlobal from "../../Context/store/AuthGlobal"
import  logoutUser  from "../../Context/actions/Auth.actions"
//import  useEffect  from 'react/cjs/react.development';

const UserProfile = (props) => 
    const context = useContext(AuthGlobal);
    const [userProfile, setUserProfile] = useState();
    const [orders, setOrders] = useState();

    useFocusEffect(
        
        useCallback(() => 
        if(
            context.stateUser.isAuthenticated === false ||
            context.stateUser.isAuthenticated === null
        ) 
            props.navigation.navigate("Login")
        

        AsyncStorage.getItem("jwt")
        .then((res) => 
            axios
                .get(`$baseURLusers/$context.stateUser.user.userId`, 
                    headers:  Authorization: `Bearer $res` ,
                )
                .then((user) => setUserProfile(user.data))
        )
        .catch((error) => console.log(error))

        axios
        .get(`$baseURLorders`)
        .then((x) => 
            const data = x.data;
            console.log(data)
            const userOrders = data.filter(
                (order) => order.user._id === context.stateUser.user.userId
            );
            setOrders(userOrders);
        )
        .catch((error) => console.log(error))

    return () => 
        setUserProfile();
        setOrders();
    

    , [context.stateUser.isAuthenticated]))

    return(
        <Container style=styles.container>
            <ScrollView contentContainerStyle=styles.subContainer>
                <Text style= fontSize: 30>
                    userProfile ? userProfile.name : ""
                </Text>
                <View style=marginTop: 20>
                    <Text style=margin: 10>
                        Email: userProfile ? userProfile.email : ""
                    </Text>
                    <Text style=margin: 10>
                        Phone: userProfile ? userProfile.phone : ""
                        
                    </Text>
                    
                </View>
                
                <View style= marginTop: 80 >
                    <Button title="Sign Out" onPress=() => [
                        AsyncStorage.removeItem("jwt"),
                        logoutUser(context.dispatch)
                    ]/>
                </View>
                <View style=styles.order>
                   <Text style= fontSize: 20 >My Orders</Text>
                   <View>
                       orders ? (
                           orders.map((x) => 
                               return <OrderCard key=x.id ...x />;
                           )
                       ) : (
                           <View style=styles.order>
                               <Text>You have no orders</Text>
                           </View>
                       )
                   </View>
               </View>
            </ScrollView>
        </Container>
    )


const styles = StyleSheet.create(
    container: 
        flex: 1,
        alignItems: "center"
    ,
    subContainer: 
        alignItems: "center",
        marginTop: 60
    ,
    order: 
        marginTop: 20,
        alignItems: "center",
        marginBottom: 60
    
)

export default UserProfile;

【讨论】:

以上是关于CastError:模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose CastError:模型“Post”的路径“_id”处的值“未定义”转换为 ObjectId 失败

MongooseError [CastError]:模型“List”的路径“_id”的值“ name:'C'”转换为 ObjectId 失败

CastError:模型的路径“_id”处的值“:id”转换为 ObjectId 失败

CastError:对于猫鼬中模型的路径“_id”处的值“findByName”,转换为 ObjectId 失败

CastError:对于猫鼬中模型的路径“_id”处的值“findByName”,转换为 ObjectId 失败

CastError:模型“Company”的路径“_id”处的值“...”转换为 ObjectId 失败