Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Cannot read property 'firstName' of undefined - using 'props' in react

I am currently learning React and have hit a problem.

I retrieve a list of JSON information relating to documents which I then pass the json as props into the following const:

const Document = props => {
  console.log(JSON.stringify(props));
  return(
    <div className="row">
      <div className="col-3">{props.dateOnLetter}</div>
      <div className="col-1">{props.personFrom.firstName}</div>
      <div className="col-1">{props.personFrom.lastName}</div>
      <div className="col-1">{props.personTo.firstName}</div>
      <div className="col-1">{props.personTo.lastName}</div>
    </div>
  );
};

The JSON looks like this:

{
    "dateOnLetter":"2012-04-23T18:25:43.511+0000",
    "personFrom":{
        "id":"5b637d319e30ed3f8c322c64",
        "firstName":"Georgexxx",
        "lastName":"TheCatxxx"
    }
}

It complains that the personTo attribute doesnt exist; however the reason I want to include it is that it may exist in some rows.

It complains about the line:

<div className="col-1">{props.personTo.firstName}</div>

The error is:

TypeError: Cannot read property 'firstName' of undefined - using 'props' in react

So, any idea how I can solve this elegantly?

like image 739
Storms786 Avatar asked Apr 11 '26 12:04

Storms786


1 Answers

You need to guard against it not existing. There are a couple of ways to do that. For instance, the conditional operator:

<div className="col-1">{props.personTo ? props.personTo.firstName : ""}</div>
<div className="col-1">{props.personTo ? props.personTo.lastName : ""}</div>

Live Example:

const Document = props => {
  console.log(JSON.stringify(props));
  return(
    <div className="row">
      <div className="col-3">{props.dateOnLetter}</div>
      <div className="col-1">{props.personFrom.firstName}</div>
      <div className="col-1">{props.personFrom.lastName}</div>
      <div className="col-1">{props.personTo ? props.personTo.firstName : ""}</div>
      <div className="col-1">{props.personTo ? props.personTo.lastName : ""}</div>
    </div>
  );
};

ReactDOM.render(
  <Document dateOnLetter="today" personFrom={{firstName: "Joe", lastName: "Bloggs"}} />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Another option is to destructure your props on receipt and provide a default for the personTo property:

const Document = ({dateOnLetter, personFrom, personTo = {firstName: "", lastName: ""}}) => {
  return(
    <div className="row">
      <div className="col-3">{dateOnLetter}</div>
      <div className="col-1">{personFrom.firstName}</div>
      <div className="col-1">{personFrom.lastName}</div>
      <div className="col-1">{personTo.firstName}</div>
      <div className="col-1">{personTo.lastName}</div>
    </div>
  );
};

Live Example:

const Document = ({dateOnLetter, personFrom, personTo = {firstName: "", lastName: ""}}) => {
  return(
    <div className="row">
      <div className="col-3">{dateOnLetter}</div>
      <div className="col-1">{personFrom.firstName}</div>
      <div className="col-1">{personFrom.lastName}</div>
      <div className="col-1">{personTo.firstName}</div>
      <div className="col-1">{personTo.lastName}</div>
    </div>
  );
};

ReactDOM.render(
  <Document dateOnLetter="today" personFrom={{firstName: "Joe", lastName: "Bloggs"}} />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

You don't have to destructure in the parameter list if you don't want to, and you don't have to destructure everything if you don't want to:

const Document = props => {
  const {personTo = {firstName: "", lastName: ""}} = props;
  return(
    <div className="row">
      <div className="col-3">{props.dateOnLetter}</div>
      <div className="col-1">{props.personFrom.firstName}</div>
      <div className="col-1">{props.personFrom.lastName}</div>
      <div className="col-1">{personTo.firstName}</div>
      <div className="col-1">{personTo.lastName}</div>
    </div>
  );
};

Live Example:

const Document = props => {
  const {personTo = {firstName: "", lastName: ""}} = props;
  return(
    <div className="row">
      <div className="col-3">{props.dateOnLetter}</div>
      <div className="col-1">{props.personFrom.firstName}</div>
      <div className="col-1">{props.personFrom.lastName}</div>
      <div className="col-1">{personTo.firstName}</div>
      <div className="col-1">{personTo.lastName}</div>
    </div>
  );
};

ReactDOM.render(
  <Document dateOnLetter="today" personFrom={{firstName: "Joe", lastName: "Bloggs"}} />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
like image 148
T.J. Crowder Avatar answered Apr 14 '26 00:04

T.J. Crowder