【问题标题】:JSON Object Property not returnable - "Cannot Read Property of Undefined"JSON 对象属性不可返回 - “无法读取未定义的属性”
【发布时间】:2020-08-06 00:44:34
【问题描述】:

好的,所以我在 React 中构建了一个自定义 API。当我拨打电话时,我会取回 JSON 数据并使用 JSON.Stringify 将其存储到本地存储中:

localStorage.setItem('user', JSON.stringify(response.data))

稍后,我将这个项目调用到主页上,以便在用户使用以下方式登录后返回一些数据:

var user = JSON.parse([localStorage.getItem('user')])

这会返回对象:

{
"OrderId":0,
"IsLoggedIn":true,
"ModeOfSaleId":64,
"OriginalModeOfSaleId":64,
"SourceId":8580,
"LoginInfo":{"ConstituentId":190554,"OriginalConstituentId":190554,"UserId":"test@email.org","Status":"P","FailedAttempts":0,"LockedDate":null,"ElectronicAddress":"test@email.org"},
"CartInfo":{"PerformanceCount":0,"PackageCount":0,"ContributionCount":0,"MembershipCount":0,"UserDefinedFeeCount":0,"GiftCertificateCount":0,"PaymentCount":0,"FirstSeatAddedDateTime":null},
"BusinessFacing":false,
"IsGuest":false,
"CheckoutStatus":{"Status":"No Checkout","Date":null},
"HasLockedSeats":false,
"SeatsExpired":false
}

问题:

未嵌套的属性正常返回{user.OrderId}{user.ModeOfSaleId} 但是,尝试返回嵌套值如{user.LoginInfo.ConstituentID} 会导致错误:

Uncaught TypeError: Cannot read property 'ConstituentId' of undefined

返回{user.LoginInfo} 实际上会返回一个对象,但显然不能将其打印到字符串中。返回{user.LoginInfo["ConstituentId"]} 会导致错误:

Uncaught TypeError: Cannot read property 'ConstituentId' of undefined

所以是的,我很难过,我不知道我是如何错误地返回这个的。任何帮助表示赞赏。

【问题讨论】:

    标签: javascript json reactjs api parsing


    【解决方案1】:

    好的,所以我返回这些值的方式似乎是一个“问题”,因为 React 处理它的 Render 事件的方式。当我在componentDidMount() 事件中提取数据时,Render 事件仍然会在此之前触发。

    componentDidMount() {
      this.setState({ 
        user: JSON.parse([localStorage.getItem('user')]),
        users: { loading: true }
      });
    }
    

    所以在渲染事件中:

    render() {
        const { user, users, loading } = this.state;
        var { ConstituentId, UserId } = user.LoginInfo
    
    
        return (
            <div className="col-md-6 col-md-offset-3">
                <h1>Hi!</h1>
                <p>{UserId}</p>
                <p>You're logged in with React & Basic HTTP Authentication!!</p>
                <h3>Users from secure api end point:</h3>
                <p>
                    <Link to="/login">Logout</Link>
                </p>
            </div>
        );
    }
    

    它会触发两次,一次是在 state.usercomponentDidMount() 设置之前,然后再一次。因此,我的代码由于第一次触发渲染而出错,当时没有设置任何内容,因此出现了undefined 消息。我想出了如何通过检查登录信息对象返回为typeof object 来绕过这个问题。这是在我的渲染事件中:

    var result = (typeof user.loginInfo === 'object');
    
    if (result && loading) {
        console.log(result)
        console.log(user.LoginInfo.ConstituentId)
        var { ConstituentId, UserId } = user.LoginInfo
    }
    

    但这不是很优雅。所以,最终我通过创建一个名为 'loading' 的 state prop 重写了我在componentDidMount() 中处理卸载信息的方式:

    this.state = {
      loading: true,
      user: {}
    };
    

    componentDidMount() 我正在这样做:

    this.setState({ 
      user: JSON.parse(localStorage.getItem('user')),
      loading: false
    });
    

    render():

    const { loading, user } = this.state;
    if (!loading) {
      var { ConstituentId, UserId } = user.LoginInfo
    }
    console.log(ConstituentId)
    

    效果很好!

    基本上,我只是在等待componentDidMount() 使用loading 状态触发,方法是在函数中将其设置为false。然后我们就知道它已经加载完毕,可以成功渲染数据了。

    【讨论】:

      【解决方案2】:

      此代码适用于我:

      localStorage.setItem("user", JSON.stringify({
         "OrderId":0,
         "IsLoggedIn":true,
         "ModeOfSaleId":64,
         "OriginalModeOfSaleId":64,
         "SourceId":8580,
         "LoginInfo":{"ConstituentId":190554,"OriginalConstituentId":190554,"UserId":"test@email.org","Status":"P","FailedAttempts":0,"LockedDate":null,"ElectronicAddress":"test@email.org"},
         "CartInfo":{"PerformanceCount":0,"PackageCount":0,"ContributionCount":0,"MembershipCount":0,"UserDefinedFeeCount":0,"GiftCertificateCount":0,"PaymentCount":0,"FirstSeatAddedDateTime":null},
         "BusinessFacing":false,
         "IsGuest":false,
         "CheckoutStatus":{"Status":"No Checkout","Date":null},
         "HasLockedSeats":false,
         "SeatsExpired":false
      }));
      
      const user = JSON.parse(localStorage.getItem("user"));
      
      console.log(user.LoginInfo.OriginalConstituentId);
      
      

      【讨论】:

      • 仍然收到 Uncaught TypeError: Cannot read property 'OriginalConstituentId' of undefined 可能是 React 的问题吗?
      • 您在反应生命周期的哪个位置设置/获取数据?想到的一件事是 react 处理渲染的方式,组件将在获取数据之前渲染一次,因此您尝试访问的整个子对象可能还不存在。 Cannot read property 'OriginalConstituentId' of undefined 表示 LoginInfo 也没有定义,因此用户对象可能只是一个空对象。尝试在之前添加一个 if 语句,例如:if (user.LoginInfo) &lt;do something with user.LoginInfo.OriginalConstituentId&gt;
      • 您部分正确。这是因为 React 的 render() 函数在 componentDidMount() 之前触发的方式。详细解释见我的回答。
      【解决方案3】:

      如何使用扩展运算符来得到你想要的?

      const user = JSON.parse(localStorage.getItem('user'))
      const { ConstituentId, UserId } = user.LoginInfo
      
      console.log(ConstituentId) // 190554
      

      【讨论】:

      • 不幸的是,我仍然收到Uncaught TypeError: Cannot read property 'ConstituentId' of undefined 错误。这很奇怪,因为我发现我可以console.log(user.LoginIfo) 没有问题,甚至可以将嵌套元素包装在一个数组中:const { ConstituentId, UserId } = [user.LoginInfo] 和控制台使用0 项作为嵌套对象记录它。但是,我仍然无法访问里面的任何东西!
      • 任何访问内部属性的尝试都会导致它被定义为未定义,例如:const login = user.LoginInfo console.log(login) 正常返回一个 obj。 console.log(login.ConstituentId) 没有。我什至尝试过const login = JSON.parse(JSON.stringify(user.LoginIfo)),但返回Uncaught SyntaxError: Unexpected token u in JSON at position 0 呃!这可能是 React 固有的东西吗?正确调用嵌套obj的具体方法?
      猜你喜欢
      • 1970-01-01
      • 2016-05-24
      • 2023-03-20
      • 2019-11-13
      • 2023-04-01
      • 2018-02-04
      • 2021-04-30
      • 1970-01-01
      • 2020-11-10
      相关资源
      最近更新 更多