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

React学习项目报错:Uncaught ReferenceError及列表重渲染问题求助

你的React项目问题解决方案

我来帮你一步步搞定这两个问题:

1. 先解决"Uncaught ReferenceError: val is not defined"报错

这个错误其实是两个小问题导致的:

  • 你在setState里写了{val},这是ES6的对象简写语法,只有当你有一个同名变量时才能这么用,但这里你根本没声明过val变量,JS自然找不到它,直接报错。
  • 更重要的是,你直接修改了React的state:this.state.val.push(msg)这种写法是React的大忌,因为React的state设计成不可变的,直接改原state会让React检测不到状态变化,后续渲染肯定出问题。

正确的写法是创建一个新数组,把新消息加进去,再通过setState更新:

handleSend(msg) {
  // 用扩展运算符复制原数组,再加入新消息,不碰原state
  const updatedMessages = [...this.state.val, msg];
  this.setState({ val: updatedMessages });
}

如果你习惯用concat也可以,效果一样:

handleSend(msg) {
  const updatedMessages = this.state.val.concat(msg);
  this.setState({ val: updatedMessages });
}

2. 实现新增帖子后
    自动刷新

你之前改成this.setState({val: []})后要刷新才显示,是因为你把本地state清空了,但新数据根本没同步进来。要自动渲染,分两种情况处理:

情况1:AddMsg组件已经处理了POST请求,成功后传msg给你

如果AddMsg组件已经完成了后端POST请求,确认成功后才调用onSend(msg),那用上面的handleSend写法就够了——React检测到state里的数组变了,会自动重新渲染<ul>列表,不用刷新页面。

情况2:需要从后端拉取最新的完整消息列表

如果你的场景里可能有其他用户也在加消息,或者后端会对消息做处理(比如加ID),那最好在POST成功后重新拉取一次最新数据:

首先把componentDidMount里的fetch逻辑抽成单独方法,方便复用:

fetchMessages = () => {
  fetch('http://localhost:3003/api/msgs/')
    .then(res => res.json())
    .then(data => this.setState({ val: data }))
    .catch(console.error);
}

componentDidMount() {
  this.fetchMessages();
}

然后修改handleSend,先发送POST请求,成功后调用上面的方法拉取最新数据:

handleSend(msg) {
  // 先给后端发POST请求,把新消息传过去
  fetch('http://localhost:3003/api/msgs/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ msgdata: msg }), // 这里根据你后端接口的参数调整
  })
  .then(res => res.json())
  .then(() => {
    // 请求成功后,重新拉取最新消息列表,自动更新UI
    this.fetchMessages();
  })
  .catch(console.error);
}

这样操作后,新增消息成功后页面会自动刷新列表,不用手动刷新。

额外给你两个优化小建议

  • 别用数组index当key:你现在用index作为<li>的key,当列表有增删时,React可能会渲染出错,建议用后端返回的msg._id当key,比如<li dir="rtl" key={msg._id} className='myli'>。
  • 提前绑定this:你现在用bind(this)的方式每次render都会创建新函数,有点浪费性能,不如在构造函数里绑定:
constructor(props, context) {
  super(props, context);
  this.state = { val: [] };
  // 提前绑定this,后续直接用
  this.handleSend = this.handleSend.bind(this);
  this.deleteMsg = this.deleteMsg.bind(this);
}

然后render里直接写<AddMsg onSend={this.handleSend}/>就行啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:47:04