Unable to read prop in a React functional component passed via Redux

96 views Asked by At

Here is the sample react functional component

const GreetingPage = (props) => {
  console.log("console log", props)

  return (
    <div>
      <h1>Hello </h1>;
    </div>
  )
}

const mapStatetoProps = (state) => ({
  user: getUser(state)
});


export default connect(mapStatetoProps)(GreetingsPage)

When I do console.log(props) it shows me the following

enter image description here

If you see there is a user object there present.

I retrieve that user from props using following

 const { user } = props
  console.log("second log", user)

And I am shown the user data

    props.user: {
  "uuid": "7dd2sdfs2-c48f-40bb-98d2-251215911d4b",
  "created_at": "2019-11-08T10:03:36.838000Z",
  "username": "joe012",
  "email": "[email protected]",
  "name": "Joe",
  "phone_number": null,
  "do_refresh": false,
  "plan": null,
}

Finally, when I want to get the name of the user console.log(user.name)

It says

TypeError: Cannot read property 'username' of null

What is going wrong?

2

There are 2 answers

3
dmc85 On

In your question, you mentioned you're calling console.log(user.name) but it seems you should be calling console.log(user.username). I assume this was just a typing error and is probably not the cause of the problem but please double check that to make sure.

Assuming that's not what's causing the problem, another possibility is the fact that the user object is retrieved asynchronously. If your component renders multiple times and the user object is null for the first render(s) and then once the user object is retrieved, the component then rerenders with the user object attached to props, then that is certainly what is happening. When you call

const { user } = props
console.log("second log", user)

It doesn't throw an error if props.user is null at first. But when you call user.username, that does throw an error since you cannot call a property on null or undefined. To fix this, you must make some kind of a check that user is not null before calling user.username. For example:

if(user) {
  console.log(user.username)
}

Or if you use ES2020 or TS 3.7+, you could use optional chaining: user?.username so that if user is falsy then it will just log undefined instead of throwing an error.

A third possibility is the get method in lodash in which you would put _.get(user, 'username') in order to ensure the user object is not null before calling an attribute on it.

0
Aftab22 On

Can your try this: 1.Destructuring props

const GreetingPage = ({user}) => {
console.log(user)
  return (
    <div>
      <h1>Hello </h1>;
    </div>
  )
}

const mapStatetoProps = (state) => ({
  user: getUser(state)
});


export default connect(mapStatetoProps)(GreetingsPage)

Or 2.Destructuring Child element

const GreetingPage = ({user:{username}}) => {
console.log(user)
  return (
    <div>
      <h1>Hello </h1>;
    </div>
  )
}

const mapStatetoProps = (state) => ({
  user: getUser(state)
});


export default connect(mapStatetoProps)(GreetingsPage)

Or 3.Parsing object before sending it as porps

const GreetingPage = ({user}) => {
console.log(user)
  return (
    <div>
      <h1>Hello </h1>;
    </div>
  )
}

const mapStatetoProps = (state) => ({
  user: JSON.parse(getUser(state))
});


export default connect(mapStatetoProps)(GreetingsPage)