You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express全局变量结合Handlebars渲染时出现_id读取错误排查

解决Handlebars自定义Helper调用时的TypeError问题

问题场景

在Express项目中,通过app.use设置全局变量res.locals.user存储登录用户信息;在Handlebars的index.hbs模板中调用自定义helper函数updateIcon,传入帖子所属用户、全局登录用户及帖子ID,期望仅登录用户自身的帖子显示编辑图标,但运行时触发TypeError: Cannot read properties of undefined (reading '_id')错误。

相关代码

app.js 全局变量设置

// Set global variable
app.use(function (req, res, next) {    
    res.locals.user = req.user || null    
    next()
})

index.hbs 模板代码

<h1>All posts</h1>
<div class="row">    
    {{#each posts}}        
        <div class="col s12 m4">
            <div class="card">                      
                <div class="card-image">           
                    {{{updateIcon user ../user _id}}}
                </div>
                <div class="card-content center-align">
                    <h5>{{title}}</h5>
                    <p>{{body)}}</p>
                    <br>
                    <div class="chip">
                        <img src="{{user.image}}" alt="">
                        <a href="/stories/user/{{user._id}}">{{user.displayName}}</a>
                    </div>
                </div>
                <div class="card-action center-align">
                    <a href="/stories/{{_id}}" class="btn grey">Read More</a>
                </div>
            </div>
        </div>
    {{else}}
        <p>No posts</p>
    {{/each}}
</div>

hbs.js 自定义Helper函数

updateIcon: function (postUser, loggedInUser, postId, floating = true) {
      console.log(`${postUser._id} ${loggedInUser._id}`)
        if (postUser._id.toString() === loggedInUser._id.toString()) {        
          if (floating) {
            return `<a href="/posts/update/${postId}" class="btn-floating halfway-fab blue"><i class="fas fa-edit fa-small"></i></a>`
          } else {
            return `<a href="/posts/update/${postId}"><i class="fas fa-edit"></i></a>`
          }
        } else {
          return ''
        }
      },

错误原因分析

  1. 未登录时全局用户为null:当用户未登录时,res.locals.user被设为null,此时模板中传入的../user为null,在helper中访问loggedInUser._id会触发错误。
  2. 帖子用户字段可能缺失:部分帖子数据的user字段可能不存在或为undefined,访问postUser._id也会引发错误。
  3. 模板语法错误:模板中{{body)}}使用了错误的右括号,虽不直接导致当前TypeError,但会影响模板渲染。

解决方案

1. 给Helper添加空值检查

修改updateIcon函数,先确保postUser和loggedInUser存在且包含_id属性,再执行后续逻辑:

updateIcon: function (postUser, loggedInUser, postId, floating = true) {
    // 先校验参数有效性
    if (!postUser || !loggedInUser || !postUser._id || !loggedInUser._id) {
        return '';
    }
    if (postUser._id.toString() === loggedInUser._id.toString()) {        
        if (floating) {
            return `<a href="/posts/update/${postId}" class="btn-floating halfway-fab blue"><i class="fas fa-edit fa-small"></i></a>`;
        } else {
            return `<a href="/posts/update/${postId}"><i class="fas fa-edit"></i></a>`;
        }
    } else {
        return '';
    }
},

2. 修正模板语法错误

将index.hbs中的{{body)}}改为{{body}}:

<p>{{body}}</p>

3. 模板中提前判断登录状态(可选优化)

在调用helper前先判断全局用户是否存在,减少无效执行:

<div class="card-image">           
    {{#if ../user}}
        {{{updateIcon user ../user _id}}}
    {{/if}}
</div>

效果说明

修改后,无论用户是否登录,或者帖子用户字段是否缺失,都不会触发TypeError;仅当登录用户是帖子作者时,才会显示编辑图标。

内容的提问来源于stack exchange,提问作者Jyotirmoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:27:42