【问题标题】:Cast to ObjectId failed for value "undefined" at path "_id" for model "Post""对于模型“Post”的路径“_id”处的值“未定义”,转换为 ObjectId 失败
【发布时间】:2018-02-25 17:50:47
【问题描述】:

恐怕是 VueJs、Vuex 和 MongoDB 的一些初学者问题

我无法正确设置删除功能。将帖子添加到我的状态后出现此错误:

对于模型路径“_id”处的值“未定义”,转换为 ObjectId 失败 “发布”“

一旦我刷新页面,它就会完美运行。我知道这是因为一旦添加,除非我刷新浏览器(这会触发“从后端获取所有帖子”功能),否则我新添加的帖子没有“_id”键。

在这里和那里阅读了很多类似的问题,但我没能找到我能真正理解并适应我的情况的东西。如何强制服务器返回 _id 密钥并更新我的商店客户端,这样我就不必刷新页面来获取它?

我的 NewPost.vue 组件:

<template>
  <div class="posts">
    <h1>Add Post</h1>
      <div class="form">
        <div>
          <input type="text" name="title" placeholder="TITLE" v-model="title">
        </div>
        <div>
          <textarea rows="15" cols="15" placeholder="DESCRIPTION" v-model="description"></textarea>
        </div>
        <div>
          <button class="app_post_btn" @click="addPost">Add</button>
        </div>
      </div>
  </div>
</template>

<script>
import PostsService from "@/services/PostsService";
export default {
  name: "NewPost",
  data() {
    return {
      title: "",
      description: ""
    };
  },
  methods: {
    addPost() {
      const newPost = {
        title: this.title,
        description: this.description
      };
      this.$store.dispatch("ADD_POST", newPost);
      this.$router.push({ name: "Posts" });
    }
  }
};
</script>

Posts.vue 组件:

<template>
    <div  class="container posts"
      :class= "{'night-mode': nightMode}">
        <h1>Posts</h1>
        <div class="row">
            <b-card
            v-if="posts"
            v-for="post in posts"
            :key="post.id"
            :title="post.title"
            img-src="https://lorempixel.com/600/300/food/5/"
            img-alt="Image"
            img-top
            tag="article"
            style="max-width: 20rem;"
            class="mb-2 mr-5">
                <p class="card-text">
                    {{post.description}}
                </p>
                <div class="card-actions">
                    <b-button size='lg' variant="outline-danger" @click="deletePost(post._id)">Delete</b-button>
                    <b-button size='lg' variant="outline-success" :to="{ name: 'EditPost', params: { id: post._id } }">Edit Post</b-button>
                </div>
            </b-card>
        </div>



    </div>

</template>
<script>
import PostsService from "../services/PostsService";
import axios from "axios";

export default {
  name: "Posts",
  data() {
    return {};
  },
  methods: {
    deletePost(id) {
      return this.$store.dispatch("DELETE_POST", id);
    }
  },

  computed: {
    nightMode() {
      return this.$store.getters.getNightMode;
    },
    posts() {
      return this.$store.getters.posts;
    }
  },
};
</script>

还有这样的商店:

import Vuex from "vuex";
import Vue from "vue";
import axios from "axios";

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    nightMode: false,
    posts: []
  },
  mutations: {
    toggleNightMode(state, payload) {
      state.nightMode = payload;
    },
    CURRENT_POSTS(state, { posts }) {
      state.posts = posts;
    },
    ADD_POST(state, { newPost }) {
      state.posts.unshift({ ...newPost });
    },
    DELETE_POST(state, id) {
      for (let post of state.posts) {
        if (post._id === id) {
          state.posts.splice(state.posts.indexOf(post), 1);
        }
      }
    }
  },
  actions: {
    GET_CURRENT_POSTS({ commit }) {
      const url = "http://localhost:8081/posts";
      return axios
        .get(url)
        .then(response => {
          commit("CURRENT_POSTS", { posts: response.data.posts });
        })
        .catch(error => console.log(error));
    },
    DELETE_POST({ commit }, id) {
      const url = "http://localhost:8081/posts/";
      return axios
        .delete(url + id)
        .then(response => {
          console.log(response);
          commit("DELETE_POST", id);
        })
        .catch(error => console.log(error));
    },
    ADD_POST({ commit }, newPost) {
      const url = "http://localhost:8081/posts/";
      commit("ADD_POST", { newPost });
      return axios
        .post(url, newPost)
        .then(response => {
          console.log(response);
        })
        .catch(error => console.log(error));
    }
  },

  getters: {
    getNightMode: state => state.nightMode,

    posts: state => state.posts
  }
});

非常感谢大家!

编辑:服务器端代码

server/src/app.js

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const morgan = require("morgan");

const app = express();
app.use(morgan("combined"));
app.use(bodyParser.json());
app.use(cors());

app.listen(process.env.PORT || 8081);

var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/posts");
var db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error"));
db.once("open", function(callback) {
  console.log("Connection Succeeded");
});

var Post = require("./models/post");

// Fetch all posts
app.get("/posts", (req, res) => {
  Post.find({}, "title description", function(error, posts) {
    if (error) {
      console.error(error);
    }
    res.send({
      posts: posts
    });
  }).sort({ _id: -1 });
});

// Add new post
app.post("/posts", (req, res) => {
  var db = req.db;
  var title = req.body.title;
  var description = req.body.description;
  var new_post = new Post({
    title: title,
    description: description
  });

  new_post.save(function(error) {
    if (error) {
      console.log(error);
    }
    return axios
      .post(url, newPost)
      .then(response => {
        console.log(newPost);
    res.send({
      success: true,
      message: "Post saved successfully!"
    });
  });
});

//fetch a single post

app.get("/post/:id", (req, res) => {
  var db = req.db;
  Post.findById(req.params.id, "title description", function(error, post) {
    if (error) {
      console.log(error);
    }
    res.send(post);
  });
});

// Update a post
app.put("/posts/:id", (req, res) => {
  var db = req.db;
  Post.findById(req.params.id, "title description", function(error, post) {
    if (error) {
      console.error(error);
    }
    post.title = req.body.title;
    post.description = req.body.description;
    post.save(function(error) {
      if (error) {
        console.log(error);
      }
      res.send({
        success: true
      });
    });
  });
});

// Delete a post
app.delete("/posts/:id", (req, res) => {
  var db = req.db;
  Post.remove(
    {
      _id: req.params.id
    },
    function(err, post) {
      if (err) res.send(err);
      res.send({
        success: true
      });
    }
  );
});

server/src/models/post.js

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

var PostSchema = new Schema({
  title: String,
  description: String
});

var Post = mongoose.model("Post", PostSchema);
module.exports = Post;

【问题讨论】:

  • 请出示相关的服务器端代码

标签: javascript mongodb vue.js vuex


【解决方案1】:

您不能强制服务器返回 _id 密钥。

您必须将问题告诉您的后端同事,并要求他在回复中添加_id

【讨论】:

  • 好吧,谢谢,你让我走对了方向!我刚刚在响应中添加了 _id 并将其添加到商店的 ADD_POST 操作中,就在提交之前。现在可以使用了。
猜你喜欢
  • 2021-03-13
  • 2021-06-05
  • 2021-05-12
  • 2019-06-26
  • 2020-05-11
  • 2021-06-02
  • 2019-10-10
  • 2018-03-17
  • 2023-03-28
相关资源
最近更新 更多