【问题标题】:CastError: Cast to ObjectId failed for value "undefined" at path "_id" for model "User"CastError:模型“用户”的路径“_id”处的值“未定义”转换为 ObjectId 失败
【发布时间】: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(`${baseURL}users/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(`${baseURL}users/${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(`${baseURL}users/${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)

标签: javascript node.js reactjs express mongoose


【解决方案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(`${baseURL}users/${context.stateUser.user.userId}`, {
                    headers: { Authorization: `Bearer ${res}` },
                })
                .then((user) => setUserProfile(user.data))
        })
        .catch((error) => console.log(error))

        axios
        .get(`${baseURL}orders`)
        .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;

【讨论】:

    猜你喜欢
    • 2020-07-31
    • 2018-03-17
    • 2021-06-05
    • 2014-06-20
    • 2020-11-19
    • 2021-07-04
    • 2017-08-18
    • 2016-11-11
    • 2017-03-26
    相关资源
    最近更新 更多