【问题标题】:TypeError: Cannot read properties of null (reading 'items')TypeError: 无法读取 null 的属性(读取 \'items\')
【发布时间】:2023-01-14 08:00:16
【问题描述】:

错误:抛出错误; // 未处理的“错误”事件

类型错误:无法读取 null 的属性(读取“项目”) 在 C:\Users\shiva\Desktop\Web Development\todolist\app.js:105:17

在第一个 app.post 方法 -> else 语句中获取错误。坚持了将近一天。 ps:代码可能无法运行,因为我更改了数据库链接


    const express = require("express");
    const bodyParser = require("body-parser");
    const mongoose = require("mongoose");
    const _ = require("lodash");
    
    const app = express();
    
    app.set('view engine', 'ejs');
    
    app.use(bodyParser.urlencoded({extended: true}));
    app.use(express.static("public"));
mongoose.connect("mongodb+srv://adminshivam:refd3sfde@cluster0.3igye.mongodb.net/todolistDB");


    
    const itemsSchema = { 
      name: String
    };
    
    const Item = mongoose.model("Item", itemsSchema);
    
    
    const item1 = new Item({
      name: "Welcome to your todolist!"
    });
    
    const item2 = new Item({
      name: "Hit the + button to add a new item."
    });
    
    const item3 = new Item({
      name: "<-- Hit this to delete an item."
    });
    
    const defaultItems = [item1, item2, item3];
    
    const listSchema = {
      name: String,
      items: [itemsSchema]
    };
    
    const List = mongoose.model("List", listSchema);
    
    
    app.get("/", function(req, res) {
    
      Item.find({}, function(err, foundItems){
    
        if (foundItems.length === 0) {
          Item.insertMany(defaultItems, function(err){
            if (err) {
              console.log(err);
            } else {
              console.log("Successfully savevd default items to DB.");
            }
          });
          res.redirect("/");
        } else {
          res.render("list", {listTitle: "Today", newListItems: foundItems});
        }
      });
    
    });
    
    app.get("/:customListName", function(req, res){
      const customListName = _.capitalize(req.params.customListName);
    
      List.findOne({name: customListName}, function(err, foundList){
        if (!err){
          if (!foundList){
            //Create a new list
            const list = new List({
              name: customListName,
              items: defaultItems
            });
            list.save();
            res.redirect("/" + customListName);
          } else {
            //Show an existing list
    
            res.render("list", {listTitle: foundList.name, newListItems: foundList.items});
          }
        }
      });
    
    
    
    });
    
    app.post("/", function(req, res){
    
      const itemName = req.body.newItem;
      const listName = req.body.list;
    
      const item = new Item({
        name: itemName
      });
    
      if (listName === "Today"){
        item.save();
        res.redirect("/");
      } else {
        List.findOne({name: listName}, function(err, foundList){
          foundList.items.push(item);
          foundList.save();
          res.redirect("/" + listName);
        });
      }
    });
    
    app.post("/delete", function(req, res){
      const checkedItemId = req.body.checkbox;
      const listName = req.body.listName;
    
      if (listName === "Today") {
        Item.findByIdAndRemove(checkedItemId, function(err){
          if (!err) {
            console.log("Successfully deleted checked item.");
            res.redirect("/");
          }
        });
      } else {
        List.findOneAndUpdate({name: listName}, {$pull: {items: {_id: checkedItemId}}}, function(err, foundList){
          if (!err){
            res.redirect("/" + listName);
          }
        });
      }
    
    
    });
    
    app.get("/about", function(req, res){
      res.render("about");
    });
    
    app.listen(3000, function() {
      console.log("Server started on port 3000");
    });

上面代码的错误链接 foundList.items.push(item);

列表.ejs


    <%- include("header") -%>
    
      <div class="box" id="heading">
        <h1> <%= listTitle %> </h1>
      </div>
    
      <div class="box">
        <% newListItems.forEach((listItem) => { %>
          <form action="/delete" method="post">
            <div class="item">
              <input type="checkbox" name="checkbox" value="<%= listItem._id %>" onChange="this.form.submit()">
              <p><%=  listItem.name  %></p>
            </div>
            <input type="hidden" name="listName" value="<%= listTitle %>"></input>
          </form>
          <% });%>
    
          <form class="item" action="/" method="post">
            <input type="text" name="newItem" placeholder="New Item" autocomplete="off">
            <button type="submit" name="list" value="<%= listTitle %> ">+</button>
          </form>
      </div>
    
    <%- include("footer") -%>

【问题讨论】:

    标签: node.js mongodb mongodb-query ejs


    【解决方案1】:

    问题似乎出在您的架构上,您没有以正确的方式进行处理,而不是像这样将对象传递给moongose.model

    const itemsSchema = { 
      name: String
    };
    
    const Item = mongoose.model("Item", itemsSchema);
    

    您应该使用 mongoose 中的 Schema 类创建一个模式,因此请尝试以下操作:

    const mongoose = require("mongoose");
    const { Schema } = mongoose
    
    const itemsSchema = new Schema({
      name: {type: String, required: true}
    })
    
    const Item = mongoose.model("Item", itemsSchema)
    

    在你的listSchema 中执行以下操作:

    // removed const defaultItems = [item1, item2, item3];
    
    const listSchema = new Schema({
      name: {type: String, required: true},
      // define an array of id that references the Item schema
      items: [{type: ObjectId, ref: "Item", required: true, default: [] }]
    });
    
    const List = mongoose.model("List", listSchema);
    
    // the object named as list1 will contain a reference to id of  item1, item2 and item3.
    
    const list1 = new List({name: "list1", items: [item1._id, item2._id, item3._id]}).save()
    

    再往上,在您的post api 中:

    app.post("/", async function(req, res){
    
      const itemName = req.body.newItem;
      const listName = req.body.list;
      try {
        const item = new Item({ name: itemName });
    
        if (listName === "Today") {
          await item.save();
          res.redirect("/");
        } else {
          // save the item id to items field from list schema
          const list = await List.findOne({ name: listName })
          list.items.push(item._id)
          await list.save()
    
          // don't make a redirect within the database query
          res.redirect("/" + listName);
        }
      } catch(err) {
        // If some error was threw handle it here
        // you can handle mongoose errors as follow:
        if(err instanceof mongoose.Error) {
          // use a custom message or err.message
          res.status(500).json({message: "error with Db"})
        }
        res.status(500).json({message: "something went wrong"})
      }
    });
    

    请参阅the docs 了解更多信息,因为您在模式之间使用引用我建议您查看populate method,因为您将来可能需要它。也可以从 mongoose 查看可用的queries,几乎所有你需要的都在文档中。希望我帮助了你!

    【讨论】:

    • 我尝试了您的解决方案,但仍然遇到相同的错误,控制台一直在 app.js 的第 105 行引用项目 null,即 foundList.items.push(item);
    • 糟糕的是,我没有注意到您正在以与 itemsSchema 相同的方式制作 listSchema,我将编辑我的答案。
    • @YagoBiermann 并且您在 findOne 之后不需要 exec() , findOne 与 find() 不同,它不返回光标而是返回一个对象
    • 感谢@YagoBiermann 使用上述解决方案解决了问题
    【解决方案2】:

    只需删除 ejs 文件中的空间 ?">+

    【讨论】:

      猜你喜欢
      • 2022-01-12
      • 2021-12-04
      • 2021-12-17
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      • 2022-11-17
      相关资源
      最近更新 更多