【问题标题】:Array.length is returning undefined when page is refreshed刷新页面时,Array.length 返回未定义
【发布时间】:2019-12-16 09:32:57
【问题描述】:

当我检查长度 (array.length) 时,我有一个数组返回未定义,只有页面被刷新。

如果我在 chrome 的新选项卡中打开本地环境,一切正常,并且我得到数组的长度。仅在刷新页面一次后,页面崩溃并且我收到以下错误: “TypeError:无法读取未定义的属性‘长度’”。

我正在为项目使用 React、React 的 Context API(我从上下文提供程序获取数组)和 Nextjs。我感觉这个问题与 SSR 有关,但我不完全确定。

这是与问题相关的相关代码。

上下文提供者

export function CartProvider(props) {
    let initializeState;
    if (typeof window !== 'undefined') {
        initializeState = JSON.parse(sessionStorage.getItem('cart'));
        if (initializeState === null) {
            initializeState = [];
        }
    }

    // Sets the cart
    const [ cart, setCart ] = useState(initializeState);
    return (
        <CartContext.Provider
            value={{ cart, setCart, checkCart, addItem, deleteItem, quantityIncrease, quantityDecrease }}
        >
            {props.children}
        </CartContext.Provider>
    );
}

这是使用 Context Provider 的代码

Cart.js

import React, { Fragment, useContext } from 'react';
import ShoppingCart from '../components/ShoppingCart';
import { CartContext } from '../contexts/CartContext';
const cart = () => {
    const { cart } = useContext(CartContext);

    return (
        <Fragment>
            {cart.length !== 0 ? (
                <ShoppingCart />
            ) : (
                <div>
                    <h1>Your cart is empty</h1>
                </div>
            )}
        </Fragment>
    );
};

export default cart;

非常感谢任何帮助!

【问题讨论】:

  • 如果.length 返回undefined 那么它不是一个数组。
  • 我已经使用 Array.isArray(cart) 检查了数组,它返回数组。刷新页面时出现错误。
  • 好的,那你的问题是什么?刷新页面后,它不是数组而是其他东西,因此它的.length 返回undefined
  • 当我简单的console.log(cart),不检查长度的时候,页面总是返回[],这是一个数组。无论我是否刷新页面,都会发生这种情况。
  • 显示此console.log(cart, typeof cart, Array.isArray(cart), cart.length)

标签: javascript reactjs next.js


【解决方案1】:

我认为您的错误与 SSR 有关。
如果您使用 SSR 运行代码,initializeState 将收到 undefined。
但 initializeState 应该是您所期望的 Array。
所以,我建议你改变你的代码:

// Change
    let initializeState;
    if (typeof window !== 'undefined') {
        initializeState = JSON.parse(sessionStorage.getItem('cart'));
        if (initializeState === null) {
            initializeState = [];
        }
    }

// To
    let initializeState = [];
    if (typeof window !== 'undefined' && sessionStorage.getItem('cart')) {
        initializeState = JSON.parse(sessionStorage.getItem('cart'));
    }

您可以通过在调用 JSON.parse 时捕获错误来使代码更安全。但是,如果您确保 sessionStorage.getItem('cart') 始终正确,则可以保留此代码。

【讨论】:

    【解决方案2】:

    这是一个异步问题。该变量在评估时未初始化,这就是您获得的方式:

    “TypeError: 无法读取未定义的属性‘长度’”

    当您像这样使用提供者时尝试应用保护模式:

    import React, { Fragment, useContext } from 'react';
    import ShoppingCart from '../components/ShoppingCart';
    import { CartContext } from '../contexts/CartContext';
    const cart = () => {
        const { cart } = useContext(CartContext);
    
        return (
            <Fragment>
                {(cart && (cart.length !== 0)) ? (
                    <ShoppingCart />
                ) : (
                    <div>
                        <h1>Your cart is empty</h1>
                    </div>
                )}
            </Fragment>
        );
    };
    
    export default cart;
    

    快速解释:

    cart && (cart.length !== 0)
    

    翻译为:

    当符号“购物车”的计算结果为 truthy 值时,

    THEN 返回表达式“cart.length !== 0”的结果,

    否则返回错误

    这样你就可以在运行时“保护”不安全的代码。

    【讨论】:

    • 感谢您的回复,但是,这似乎没有奏效。我仍然得到 TypeError: Cannot read property 'length' of undefined 当我运行该代码时。
    • @RogyBear 真奇怪!看看这里:jsfiddle.net/s3de1j8o/10
    猜你喜欢
    • 2021-11-18
    • 2021-09-22
    • 2020-08-25
    • 2020-01-05
    • 2020-09-30
    • 2017-11-16
    • 2020-07-19
    • 2018-02-23
    • 1970-01-01
    相关资源
    最近更新 更多