【问题标题】:RangeError: invalid array lengthRangeError:无效的数组长度
【发布时间】:2019-11-29 03:29:40
【问题描述】:

我想从对象上的键中获取一个数组,但是当对象为空时长度应该为 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>
    );
  }

【问题讨论】:

    标签: javascript arrays reactjs


    【解决方案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]))]
    

    【讨论】:

    • 我的成分都不会有负值。问题所在的错误已解决,但我现在遇到另一个错误(检查第一个答案中的 cmets)
    【解决方案2】:

    我正在学习相同的课程并遇到相同的错误。检查您的 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;
        }
        };    
    

    【讨论】:

      【解决方案3】:

      我真的不明白你为什么要对键进行额外的映射并创建一个多维数组,但是如果你想为每个键呈现一个成分,你可以将你的代码更改为:

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

      【讨论】:

      • 实际上,我是 React 的新手,我正在学习一门课程。复制代码后,错误消失了,但我的浏览器又抛出了另一个错误:Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops. 有什么解决方案吗?
      • 您是否在渲染方法中的某个地方调用setState
      • 不,我不是。你可以查看我的完整代码here
      • thisthis
      • 从截图看来错误来自ingredientHandler 方法,但我在你的代码中找不到它。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        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
                    });
        
        

        我的错误是由于价格值中有一个小数字符串。

        【讨论】:

          【解决方案6】:

          我遵循相同的课程并面临相同的问题。包含 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;
          

          【讨论】:

            【解决方案7】:

            和你一样的错误,可能是添加成分的错误。

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

            【讨论】:

              【解决方案8】:

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

              通过使每个字符都在相同的情况下,问题得到解决:

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

              【讨论】:

                【解决方案9】:

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

                例如在下面的代码中: 错误是 '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
                        });
                    }

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                    【解决方案11】:

                    我正在学习相同的课程,请检查您在数据库中使用的成分名称,这些名称应与BuildControls.js 中的相同,成分类型应与您在数据库中写入的相同。这肯定会解决你的问题。

                    发生此错误是因为选择了错误的名称,这就是它显示 Invalid array length 的原因。

                    【讨论】:

                      猜你喜欢
                      • 2020-01-31
                      • 2019-08-19
                      • 2016-12-18
                      • 1970-01-01
                      • 2018-12-28
                      • 2021-10-05
                      • 2017-07-28
                      • 2016-12-19
                      • 1970-01-01
                      相关资源
                      最近更新 更多