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

React仪表盘在Safari浏览器中出现TypeError的问题排查求助

解决React仪表盘在Safari中选择分区时参数变为undefined的问题

嘿,这个Safari下的兼容性问题确实挺头疼的,我来帮你一步步排查和解决!

首先,从你抛出的TypeError: undefined is not an object (evaluating 'data[temp]["usage"]')来看,核心问题是data[temp]不存在,而temp来自partition.toLowerCase(),说明传递给Charts组件的partition参数在Safari下变成了undefined。我们可以从以下几个方向入手:

1. 先确认状态更新是否正确触发

首先检查你处理分区选择的事件逻辑,比如<select>的onChange方法。在Safari里,事件对象的取值有时候会和其他浏览器有细微差异,建议在更新状态前先打印选中的值:

const handlePartitionSelect = (e) => {
  const selectedValue = e.target.value;
  console.log("选中的分区值:", selectedValue); // 在Safari控制台看这个输出
  setPartition(selectedValue);
};

如果这里的selectedValue是正确的,那问题出在后续的渲染/参数传递环节;如果输出是undefined,那说明事件绑定或取值有问题(不过现在大部分场景下e.target.value是通用的,可能是事件处理逻辑有遗漏)。

2. 给Charts组件添加防御性检查

即使参数传递过程中出现异常,我们也可以在Charts组件里提前拦截,避免崩溃。修改你的Charts组件代码:

const Charts = ({ data, partition }) => {
  // 先验证核心参数是否存在
  if (!partition || !data) {
    console.warn("Charts组件缺少必要参数:partition或data");
    return <div className="empty-state">暂无数据</div>;
  }

  const temp = partition.toLowerCase();
  // 检查data中是否存在对应分区的数据
  const partitionData = data[temp];
  if (!partitionData || !partitionData.usage) {
    console.warn(`未找到分区${temp}的使用数据`);
    return <div className="empty-state">暂无{partition}分区的数据</div>;
  }

  const [usageLabels, usageValues] = parseSummaryData(partitionData.usage);
  // 后续渲染逻辑...
};

这样不仅能避免报错,还能通过控制台日志快速定位问题。

3. 优化父组件的渲染逻辑

看你父组件的代码,有几个可以优化的点,可能解决Safari下的渲染异常:

  • 给map循环的元素添加唯一key:React要求列表元素必须有唯一key,虽然这不会直接导致参数undefined,但Safari可能对未加key的列表渲染有更严格的处理,容易引发状态同步问题。
  • 提前处理分区字符串,避免重复计算:把ptt.toLowerCase()的结果提前存起来,减少渲染时的计算。

修改后的父组件代码:

{partition !== 'All' && partition ? (
  <>
    <h2 className={classes.title}>{partition}</h2>
    <Charts data={chartData} partition={partition} />
  </>
) : (
  <>
    {partitionItems
      .filter(el => el !== 'All')
      .map(ptt => {
        const lowerCasePartition = ptt.toLowerCase();
        return (
          <React.Fragment key={lowerCasePartition}>
            <h2 className={classes.title}>{ptt.charAt(0).toUpperCase() + ptt.slice(1)}</h2>
            <Charts data={chartData} partition={lowerCasePartition} />
          </React.Fragment>
        );
      })}
  </>
)}

另外,在判断partition !== 'All'时,额外加了&& partition的判断,确保partition不是undefined时才渲染单分区的图表。

4. 检查chartData的加载时机

如果chartData是通过API请求获取的,要确保在数据完全加载完成后再渲染Charts组件。Safari下的网络请求时序可能和其他浏览器略有不同,比如如果在数据还未返回时就渲染组件,data[temp]自然会是undefined。

可以在父组件里加个加载状态:

const [isLoading, setIsLoading] = useState(true);
const [chartData, setChartData] = useState({});

// 模拟API请求
useEffect(() => {
  fetch('/api/summary-data')
    .then(res => res.json())
    .then(data => {
      setChartData(data);
      setIsLoading(false);
    })
    .catch(err => {
      console.error('数据加载失败:', err);
      setIsLoading(false);
    });
}, []);

// 渲染时先判断加载状态
if (isLoading) {
  return <div className="loading">加载中...</div>;
}

// 再渲染你的图表部分...

最后排查方向

如果以上方法都没用,可以检查:

  • 你的React版本是否过旧?虽然Safari是支持的,但旧版本React可能存在某些浏览器兼容性bug,建议升级到稳定版。
  • 是否使用了Safari不支持的JS语法?比如可选链操作符(?.)如果没经过Babel转译,旧版Safari可能不支持,但你的代码里没用到,不过可以排查一下其他依赖代码。

按照这些步骤排查,应该能找到问题所在!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 22:17:54