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

GET接口返回数组调用filter报Cannot read properties of undefined错误

问题根因

报错由三个问题共同导致:

  • 异步渲染时序问题:Redux中shippingDetails的初始状态未对shipping赋值,默认是undefined。组件首次渲染时,detailsShipping接口请求还未返回,此时直接调用shipping.filter()相当于对undefined执行方法,直接触发类型错误。你看到console.log(shipping)能输出完整数据,是因为接口返回后组件二次渲染时控制台打印了最新值,但首次渲染的报错已经中断了执行。
  • 数据路径不匹配:后端接口返回结构为{ filterRates: [费率数组] },但前端直接对shipping调用数组方法,实际上真正的费率数组存储在shipping.filterRates字段下,shipping本身是外层对象,不存在filter方法。
  • 代码笔误:ShippingMethodScreen.js首行导入语句写为mport React,缺少首字母i,会直接导致编译失败。
修复方案

前端代码修正

核心是增加加载状态兜底,修正数据取值路径,修复笔误:

// 修正首行笔误,补全i
import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { savePaymentMethod } from '../actions/cartActions';
import CheckoutSteps from '../components/CheckoutSteps';
import {detailsShipping} from '../actions/shippingActions';


export default function ShippingMethodScreen(props) {
  const cart = useSelector((state) => state.cart);
  const userSignin = useSelector((state) => state.userSignin);
  const { userInfo } = userSignin;
  const shippingDetails = useSelector((state) => state.shippingDetails);
  const { shipping, loading, error } = shippingDetails;
 
  const [shippingMethod, setShippingMethod] = useState('');
  

  useEffect(() => {
      dispatch(detailsShipping(userInfo._id));
    }, [dispatch]);
   
  // 等数据加载完成、数组存在时再执行过滤逻辑
  let cheapest = [];
  let bestvalue = [];
  let upsNextDay = [];
  if (!loading && shipping?.filterRates instanceof Array) {
    cheapest = shipping.filterRates.filter(rate => rate.attributes.includes('CHEAPEST'));
    bestvalue = shipping.filterRates.filter(rate => rate.attributes.includes('BESTVALUE'));
    upsNextDay = shipping.filterRates.filter(rate => rate.servicelevel.token.includes('ups_next_day_air_saver'));
  }
   
  return (
    <div>
      <CheckoutSteps step1 step2 step3></CheckoutSteps>
      {/* 增加加载、错误状态判断,避免空数据渲染 */}
      {loading && <div>加载运费选项中...</div>}
      {error && <div>运费加载失败:{error}</div>}
      {!loading && !error && (
        <div className="shipping-methods">
          {/* 遍历cheapest、bestvalue、upsNextDay渲染选项即可 */}
        </div>
      )}
    </div>
  );
}

可选后端优化

如果不想前端多取一层filterRates字段,可以修改后端返回逻辑,直接返回费率数组,减少嵌套:

// 原代码 res.send({filterRates}); 修改为
res.send(filterRates);

修改后Redux中存储的shipping直接是费率数组,无需再取.filterRates,过滤时直接调用shipping.filter()即可,注意仍需保留初始状态的非空判断。

逻辑验证

从你提供的console打印结果看,费率过滤规则本身没有问题:

  • USPS Parcel Select 带有CHEAPEST属性
  • USPS Priority Mail 带有BESTVALUE属性
  • UPS Next Day Air Saver 可以通过servicelevel.token匹配到
    只要解决上述空值和路径问题,即可正常拆分出三类费率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 00:12:16