RangeError:无效的数组长度

时间:2019-07-20 11:26:34

标签: javascript arrays reactjs

我想从对象上的键中获取一个数组,但是当对象为空时,长度应为0。当我尝试对数组使用console.log()时,数组的长度是正确的,但是我的代码卡在浏览器上抛出了以下错误,并停止了执行:

RangeError: invalid array length
burger/transformedIngredients<
src/components/Burger/Burger.js:8

   5 | const burger = (props) => {
   6 |   let transformedIngredients = Object.keys(props.ingredients).map(igKey => (
   7 |     // eslint-disable-next-line max-len,react/no-array-index-key
>  8 |     [...Array(props.ingredients[igKey])].map((_, i) => <BurgerIngredient key={igKey + i} type={igKey} />)
   9 |   )).reduce((arr, el) => (
  10 |     arr.concat(el)
  11 |   ), []);

这是我正在使用的代码:

const burger = (props) => {
  let transformedIngredients = Object.keys(props.ingredients).map(igKey => (
    // eslint-disable-next-line max-len,react/no-array-index-key
    [...Array(props.ingredients[igKey])].map((_, i) => <BurgerIngredient key={igKey + i} type={igKey} />)
  )).reduce((arr, el) => (
    arr.concat(el)
  ), []);

  if (transformedIngredients.length === 0) {
    transformedIngredients = <p>Please add some ingredients!</p>;
  }

我正在从这里经过ingredients

class BurgerBuilder extends Component {
  state = {
    ingredients: {
      salad: 0,
      bacon: 0,
      cheese: 0,
      meat: 0,
    },
    totalPrice: 4,
  };
render() {
    return (
      <Fragment>
        <Burger ingredients={this.state.ingredients} />
        <BuildControls
          ingredientAdded={this.addIngredientHandler}
          ingredientRemoved={this.removeIngredientHandler}
        />
      </Fragment>
    );
  }

11 个答案:

答案 0 :(得分:1)

如果一种成分的值为负,则可能会发生错误,例如:

state = {
  ingredients: {
    salad: -1, // this will cause the error
    bacon: 0,
    cheese: 0,
    meat: 0,
  },
  totalPrice: 4,
};

您可以通过确保不会在Array构造函数中传递负数来防止这种情况,例如,如果数字为负数,则可以传递0

[...Array(Math.max(0, props.ingredients[igKey]))]

答案 1 :(得分:1)

我正在从相同的课程中学习到反应,并且遇到了同样的问题。在您的const INGREDIENT_PRICES中,所有对象的大小写应与在buildcontrols.js中使用的大小写相同,并且在此const控件中检查uppper并检查单词的下位原因是否与INGREDIENT_PRICES匹配,然后问题将得到解决。

答案 2 :(得分:1)

在这种情况下,我通过设置Number.parseFloat并将价格值固定在价格整数上来尝试将价格值传递给查询参数时,将错误范围缩小到了,从而消除了导致字符串化十进制的错误。

purchaseContinueHandler = () => {            
            const queryParams = [];
            let price = Number.parseFloat(this.state.totalPrice).toFixed(2);

            for (let i in this.state.ingredients) {
                queryParams.push(encodeURIComponent(i) + '=' + encodeURIComponent(this.state.ingredients[i]));
            }
            queryParams.push('price=' + price);

            const queryString = queryParams.join('&'); 

            this.props.history.push({
                pathname: '/checkout',
                search: '?' + queryString
            });

该错误是由价格值中的字符串小数引起的。

答案 3 :(得分:1)

我遵循同样的路线,面临同样的问题。 totalPrice作为配料对象对象(在reducer.js文件中)的键值对包括在内,但事实并非如此,因为它是每个动作处于更新状态的单独的键值对。

修复之前-

import * as actionTypes from './actions';

const initialState = {
    ingredients: {
        salad: 0,
        bacon: 0,
        cheese: 0,
        meat: 0
    },
    totalPrice: 4,
};

const INGREDIENT_PRICES = {
    salad: 0.5,
    bacon: 1.3,
    cheese: 0.6,
    meat: 1,
};

const reducer = (state = initialState, action) => {
    switch(action.type){
        case actionTypes.ADD_INGREDIENT: return {
            ...state,
            ingredients: {
                ...state.ingredients,
                [action.ingredientName]: state.ingredients[action.ingredientName] + 1,
                `totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]`
            }
        };

        case actionTypes.REMOVE_INGREDIENT: return {
            ...state,
            ingredients: {
                ...state.ingredients,
                [action.ingredientName]: state.ingredients[action.ingredientName] - 1,
                `totalPrice: state.totalPrice - INGREDIENT_PRICES[action.ingredientName]`
            }
        }

        default : return state;
    }
};

export default reducer;

修复后-

import * as actionTypes from './actions';

const initialState = {
    ingredients: {
        salad: 0,
        bacon: 0,
        cheese: 0,
        meat: 0
    },
    totalPrice: 4,
};

const INGREDIENT_PRICES = {
    salad: 0.5,
    bacon: 1.3,
    cheese: 0.6,
    meat: 1,
};

const reducer = (state = initialState, action) => {
    switch(action.type){
        case actionTypes.ADD_INGREDIENT: return {
            ...state,
            ingredients: {
                ...state.ingredients,
                [action.ingredientName]: state.ingredients[action.ingredientName] + 1,
            },
            `totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]`
        };

        case actionTypes.REMOVE_INGREDIENT: return {
            ...state,
            ingredients: {
                ...state.ingredients,
                [action.ingredientName]: state.ingredients[action.ingredientName] - 1,
            },
            `totalPrice: state.totalPrice - INGREDIENT_PRICES[action.ingredientName]`
        }

        default : return state;
    }
};

export default reducer;

答案 4 :(得分:0)

我不太了解为什么要对键进行额外的映射并创建多维数组,但是如果要为每个键渲染一个成分,则可以将代码更改为此:

const burger = (props) => {
  let transformedIngredients = Object.keys(props.ingredients).map((igKey, i) => (
    <BurgerIngredient key={igKey + i} type={igKey} />
  ));
}

答案 5 :(得分:0)

我正在上相同的课程,并且遇到相同的错误。检查您的reducer.js文件,并将其与课程中提供的源代码进行比较。以我为例,从reducer.js传递的数组与Burger.js接收的数组不匹配。修复reducer.js文件后,该错误消失了。

修复后,我的代码如下:

    const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.ADD_INGREDIENT:
      return {
        ...state,
        ingredients: {
          ...state.ingredients,
          [action.ingredientName]: state.ingredients[action.ingredientName] + 1
        },
        totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
      };
    case actionTypes.REMOVE_INGREDIENT:
      return {
        ...state,
        ingredients: {
          ...state.ingredients,
          [action.ingredientName]: state.ingredients[action.ingredientName] - 1
        },
        totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName]
      };
    default:
      return state;
    }
    };    

答案 6 :(得分:0)

与您的错误相同,可能是添加配料时出现错误。

通过在复制对象行中将“ []”更改为“ {}”来解决我的问题。我没有注意到我使用了[]。

答案 7 :(得分:0)

我也犯了同样的错误,将'b'和'c'改为大写 在“培根”和“奶酪”中

通过在相同情况下制作每个字符,问题得以解决:

const controls=[
  {label:'salad',type:'salad'},
  {label:'bacon',type:'bacon'},
  {label:'cheese',type:'cheese'},
  {label:'meat',type:'meat'}
  ];

答案 8 :(得分:0)

感谢所有花时间提供您的答案和想法的人。 我遇到了同样的问题,解决方案是将键值更改为小写,

例如下面的代码: 错误是'Price'大写而不是'price'小写

checkoutContinuedHandler = () => {
        const queryParams = [];
        for (let ing in this.state.ingredients) {
            queryParams.push(encodeURIComponent(ing) + '=' + encodeURIComponent(this.state.ingredients[ing]));
        }
        queryParams.push('price=' + this.state.totalPrice.toFixed(2));
        const queryString = queryParams.join('&');
        this.props.history.push({
            pathname: '/checkout',
            search: '?' + queryString
        });
    }

答案 9 :(得分:0)

只需从 ...state.ingredients 中删除扩展运算符,它就会起作用!

答案 10 :(得分:-1)

我正在遵循同一课程,请检查您在数据库中使用的配料名称,这些名称应与BuildControls.js中的相同,配料类型应与您在数据库中编写的名称相同。这肯定会解决您的问题。

发生此错误是由于选择了错误的名称,这就是它说无效数组长度的原因。