1
const [book, ...rest] = this.state.details;
console.log(JSON.stringify(book, null, 2));

logs:

{
  genre: [
    {
      _id: "5ad0ecf98c1cff1e849266f3",
      name: "Fantasy",
      url: "/catalog/genre/5ad0ecf98c1cff1e849266f3",
      id: "5ad0ecf98c1cff1e849266f3"
    }
  ],
  _id: "5ad0ecfc8c1cff1e849266f7",
  title: "The Wise Man's Fear (The Kingkiller Chronicle, #2)",
  summary:
    "Picking up the tale of Kvothe Kingkiller once again, we follow him into exile, into political intrigue, courtship, adventure, love and magic... and further along the path that has turned Kvothe, the mightiest magician of his age, a legend in his own time, into Kote, the unassuming pub landlord.",
  author: {
    _id: "5ad0ecf98c1cff1e849266ee",
    first_name: "Patrick",
    family_name: "Rothfuss",
    date_of_birth: "1973-06-06T00:00:00.000Z",
    name: "Rothfuss, Patrick",
    url: "/catalog/author/5ad0ecf98c1cff1e849266ee",
    id: "5ad0ecf98c1cff1e849266ee"
  },
  isbn: "9788401352836",
  url: "/catalog/book/5ad0ecfc8c1cff1e849266f7",
  id: "5ad0ecfc8c1cff1e849266f7"
};

I want to render:

render() {
  const [book={}, ...rest] = this.state.details;
  console.log(JSON.stringify(book, null, 2));

// console.log(book.title);

 return (
   <div>
     <h2>{book.title}</h2>
     <p>{book.author.name}</p>
   </div>
 );
}

getting error: Cannot read property 'title' of undefined, if I set book's default value to empty object i am able to get title, but now i get error: Cannot read property 'name' of undefined. What's the

here's the default state

state = { details: [], loading: true };  

componentDidMount() {
  fetch(this.props.match.url)
  .then(res => res.json())
  .then(data => this.setState({ details: data, loading: false }))
  .catch(err => console.log(err));
}
6
  • 2
    show the full render method Commented May 2, 2018 at 15:09
  • what is shown when you do console.log(book.title); Commented May 2, 2018 at 15:14
  • Does your array always contain one object? Please share this.state.details Commented May 2, 2018 at 15:14
  • just updated the question! Commented May 2, 2018 at 15:14
  • title returns undefined Commented May 2, 2018 at 15:16

4 Answers 4

1

My understanding from your code and error is that the details object in the state is being fetched asynchronously, and so the component tries to render before it has the required data available.

You could return null or a loading message while the data is being fetched.

render() {
    const [book={}, ...rest] = this.state.details;
    console.log(JSON.stringify(book, null, 2));

    // console.log(book.title);

    if (!book) return null;

    return (
      <div>
        <h2>{book.title}</h2>
        <p>{book.author.name}</p>
      </div>
    );
}
Sign up to request clarification or add additional context in comments.

1 Comment

you are correct! I did if (!book.author) return null and it worked!
0

reading your comments, the details is an array, and you are doing something wrong, which is trying to access to values that are not defined because of an Async call.

so, when you do:

const [book, ...rest] = this.state.details;

you are getting the current [0] object that you have, but since you dont have anything preloaded, you will get and error trying to do book.title because book is undefined.

const [book={}, ...rest] = this.state.details;

basically you are creating a default object if there is nothing (which is the case in the first render), thats why you can see book.title(which is undefined, but book isnt) but then doing book.author.name will show it as an error, because book is defined, but it doesnt have a prop called author, thus author.name wont work.

after your async call finishes on the componentDidMount it updates the state triggering another render and then you will have the data. you using your code, while you are loading the data use the loading prop on the state that you have, so your render should be like this:

render() {
    if(this.state.loading){
        return null;
    }else{
        const [book={}, ...rest] = this.state.details;
        console.log(JSON.stringify(book, null, 2));

        return (
            <div>
                <h2>{book.title}</h2>
                <p>{book.author.name}</p>
           </div>
        );
    }
}

1 Comment

@d_oram YW, had to fix my bad answer using the fake state. glad it helped.
0

You have to init your object (book):
example

 book = {
      genre: [
        {
          _id: null,
          name: null,
          url: null,
          id: null
        }
      ],
      _id: null,
      title: null,
      summary: null,
      author: {
        _id: null,
        first_name: null,
        family_name: null,
        date_of_birth: null,
        name: null,
        url: null,
        id: null
      },
      isbn: null,
      url: null,
      id: null
    };

Comments

0

My guess is during your first render details = [], then you update the state with valid details which causes the component to rerender.

So this is erroring during the first render

Try this

render() {
  const [book={}, ...rest] = this.state.details;
  console.log(JSON.stringify(book, null, 2));

  if (ramda.isEmpty(book)) return null
  // console.log(book.title);

  return (
    <div>
      <h2>{book.title}</h2>
      <p>{book.author.name}</p>
    </div>
  );

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.