简体   繁体   English

JSON Object 属性不可返回 - “无法读取未定义的属性”

[英]JSON Object Property not returnable - “Cannot Read Property of Undefined”

Ok, so I'm building out a custom API in React.好的,所以我在 React 中构建了一个自定义 API。 When I make the calls, I'm getting JSON data back and store that into local storage with JSON.Stringify:当我拨打电话时,我将返回 JSON 数据并使用 JSON.Stringify 将其存储到本地存储中:

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

Later, I call this item onto the Homepage to return some of that data once the user is logged in using:稍后,我将这个项目调用到主页上,以便在用户使用以下方式登录后返回一些数据:

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

This returns the object:这将返回 object:

{
"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
}

The Issue:问题:

Un-nested properties return normally {user.OrderId} or {user.ModeOfSaleId} However, trying to return the nested values like {user.LoginInfo.ConstituentID} result in the error:未嵌套的属性通常返回{user.OrderId}{user.ModeOfSaleId}但是,尝试返回嵌套值(如{user.LoginInfo.ConstituentID}导致错误:

Uncaught TypeError: Cannot read property 'ConstituentId' of undefined

Returning {user.LoginInfo} actually returns an object, but obviously, can't print that to a string.返回{user.LoginInfo}实际上会返回 object,但显然不能将其打印到字符串中。 Returning {user.LoginInfo["ConstituentId"]} results in the error:返回{user.LoginInfo["ConstituentId"]}会导致错误:

Uncaught TypeError: Cannot read property 'ConstituentId' of undefined

So yeah, I'm stumped, I don't know how I'm returning this incorrectly.所以,是的,我很难过,我不知道我是如何错误地返回这个的。 Any help is appreciated.任何帮助表示赞赏。

What about using spread operator to get what you want?使用扩展运算符来获得你想要的东西怎么样?

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

console.log(ConstituentId) // 190554

This code works for me:这段代码对我有用:

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

Ok, so the way I'm returning these values seems to be an "issue" because of the way React handles it's Render event.好的,所以我返回这些值的方式似乎是一个“问题”,因为 React 处理它的 Render 事件的方式。 When I'm pulling in the data on the componentDidMount() event, a Render event still fires just before this.当我在componentDidMount()事件中提取数据时,Render 事件仍然会在此之前触发。

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

So in the Render event:所以在渲染事件中:

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

It fires TWICE, once BEFORE the state.user is set by componentDidMount() and once again after.它触发两次,一次在state.user之前由componentDidMount()设置,然后再次触发。 So, my code was erroring out because of the first firing of Render, when nothing was set, hence the undefined message.因此,由于第一次触发 Render,我的代码出错了,没有设置任何内容,因此出现了undefined的消息。 I figured out how to bypass this with checking the login info object is returning as typeof object .我想出了如何通过检查登录信息 object 返回为typeof object来绕过这个问题。 This is in my render event:这是在我的渲染事件中:

var result = (typeof user.loginInfo === 'object');

if (result && loading) {
    console.log(result)
    console.log(user.LoginInfo.ConstituentId)
    var { ConstituentId, UserId } = user.LoginInfo
}

But that's not very elegant.但这不是很优雅。 So, ultimately I re-wrote how I was handling unloaded information in componentDidMount() by creating a state prop called 'loading':因此,最终我通过创建一个名为“加载”的 state 道具重新编写了我在componentDidMount()中处理卸载信息的方式:

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

In componentDidMount() I'm doing this:componentDidMount()我这样做:

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

And in render() :render()中:

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

It works great!效果很好!

Basically, I'm just waiting for componentDidMount() to fire using the loading state by setting it to false in the function.基本上,我只是在等待componentDidMount()使用loading state 通过在 function 中将其设置为false来触发。 Then we know it's loaded and can successfully render the data.然后我们知道它已经加载并且可以成功渲染数据了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM