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

React调用setState时抛出Cannot read properties of null (reading 'toString')错误

错误分析与修复方案

核心问题定位

错误Cannot read properties of null (reading 'toString')源于以下几个代码逻辑漏洞:

1. 错误的对象/数组拷贝逻辑

const tempBusPoints = route.direction !== "IDA E VOLTA" ? { ...busPoints } : [...busPoints];

当route.direction为"IDA E VOLTA"时,代码尝试用数组展开语法拷贝对象类型的busPoints,会创建错误的数组结构(而非预期的对象)。后续访问tempBusPoints.returnBusPoints会得到undefined,引发数据处理异常,最终在渲染或API调用时触发null的toString调用。

2. 未处理找不到目标busPoint的情况

const index = tempAdjacenteBusPoints.indexOf(tempAdjacenteBusPoints.find(bp => bp.id === id));
const draggedBusPoint = tempAdjacenteBusPoints[index];

如果find方法找不到匹配id的busPoint,会返回null,此时indexOf(null)返回-1,draggedBusPoint变成undefined。直接修改undefined的属性会破坏数据结构,引发后续渲染错误。

3. Math.max处理空数组导致异常值

当所有过滤后的订单数组为空时,Math.max(...[])返回-Infinity,赋值给draggedBusPoint.order后,后续逻辑可能将这个异常值传入需要转字符串的场景,间接触发错误。

4. 直接修改原state引用

tempAdjacenteBusPoints是原state数组的浅拷贝,draggedBusPoint是数组元素的引用,直接修改其属性违反React的immutable原则,引发不可预测的组件重渲染副作用。


具体修复步骤

1. 修正busPoints拷贝逻辑

无论route.direction是什么,都保持对象拷贝(若需深拷贝内部数组,需额外处理):

// 浅拷贝busPoints对象,同时深拷贝内部数组
const tempBusPoints = {
  ...busPoints,
  goBusPoints: [...busPoints.goBusPoints],
  returnBusPoints: [...busPoints.returnBusPoints]
};

2. 增加busPoint存在性检查

在获取拖拽的busPoint前,先确认找到目标元素:

const foundBusPoint = tempAdjacenteBusPoints.find(bp => bp.id === id);
if (!foundBusPoint) {
  console.warn(`未找到ID为${id}的站点`);
  return;
}
const index = tempAdjacenteBusPoints.indexOf(foundBusPoint);
// 创建busPoint副本,避免修改原引用
const draggedBusPoint = { ...foundBusPoint };

3. 处理Math.max空数组场景

给Math.max设置默认值,避免出现-Infinity:

// 以goMaxOrder为例
const goOrders = [
  ...tempBusPoints.goBusPoints.filter(bp => bp.order !== null).map(bp => bp.order),
  ...tempAdjacenteBusPoints.filter(bp => bp.state === "added-go" && bp.order !== null).map(bp => bp.order)
];
const goMaxOrder = (goOrders.length > 0 ? Math.max(...goOrders) : 0) + 1;

同理修改returnMaxOrder和setOrder中的Math.max逻辑。

4. 更新数组元素时使用副本

修改draggedBusPoint后,替换数组中的原元素:

draggedBusPoint.state = currentDirection === "go" ? "added-go" : "added-return";
draggedBusPoint.color = "green";
draggedBusPoint.lat = lat;
draggedBusPoint.lng = lng;
// 替换数组中的原元素
tempAdjacenteBusPoints[index] = draggedBusPoint;

5. 调试辅助(可选)

在setState调用处添加try-catch,定位具体错误点:

try {
  setSelectedBusPoint(draggedBusPoint);
  setAdjacenteBusPoints(tempAdjacenteBusPoints);
} catch (err) {
  console.error("状态更新错误:", err, "当前站点数据:", draggedBusPoint);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:32:49