-1

I got access to rest of properties instead of one. I didnt catch what problem is.

I've tried:

this.props.data.imageLinks.thumbnail

this.props.data.imageLinks[thumbnail]

this.props.data.imageLinks["thumbnail"]

But other properties spew out correct value when I tried: {this.props.data.title}, {this.props.data.author}.

class Book extends React.Component {

  render() {
    console.log('prop',this.props.data.imageLinks)

    return (
      <div key={this.props.data.id}>
        <div className="book">
          <div className="book-top">
            <div 
              className="book-cover"
              style={{ 
                width: 128, 
                height: 192, 
                backgroundImage: `url(${this.props.data.imageLinks.thumbnail})`
              }}
            ></div>
            <DropDownList/>
          </div>
          <div className="book-title">{this.props.data.title}</div>
          <div className="book-authors">{this.props.data.author}</div>
        </div>
        <div>
          {/*BooksAPI.getAll().then(function(res){console.log(res)})*/}
        </div>
      </div>
    )
  }
}

This object how its look

object

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
K D
  • 15
  • 1
  • 5
  • 1
    What does `console.log(typeof this.props.data.imageLinks)` give you? – Ian Kemp Dec 30 '18 at 19:32
  • Its gave object: {smallThumbnail: "http://books.google.com/books/content?id=nggnmAEAC…J&printsec=frontcover&img=1&zoom=5&source=gbs_api", thumbnail: "http://books.google.com/books/content?id=nggnmAEAC…J&printsec=frontcover&img=1&zoom=1&source=gbs_api"} smallThumbnail: "http://books.google.com/books/content?id=nggnmAEACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api" thumbnail: "http://books.google.com/books/content?id=nggnmAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api" __proto__: Object – K D Dec 30 '18 at 19:59
  • You're probably fetching the data asynchronously? The [console is keeping a live reference](https://stackoverflow.com/a/11463190/1218980) to the object, hence it showing the data when it's fetched. – Emile Bergeron Dec 30 '18 at 20:12
  • I've fetch it async way inside DidComponentMount() in parent component and put to array. So current component got local array. May be I'm wrong... So what the usual pattern in this case ? I mean when component already rendered but didnt get data ? – K D Dec 30 '18 at 20:15
  • There's a split second where `data` is probably an empty object, and `data.imageLinks` is `undefined`, so it gives the error. Though, in the console, the fetch is finished when you're looking at it. – Emile Bergeron Dec 30 '18 at 20:24
  • I've fetch it async way inside DidComponentMount() in parent component and put to array. So current component got local array. Console.log dont show result too, I mean **this.props.data.imageLinks.thumbnail** only **this.props.data.imageLinks** correct show result. – K D Dec 30 '18 at 20:29
  • I just switched **backgroundImage: `url(${this.props.data.imageLinks.thumbnail})`** to **backgroundImage: `url(${this.props.data.imageLinks})`** - no Errors happen... just books without front cover. – K D Dec 30 '18 at 20:34

2 Answers2

0

I guess, thumbnail comes after component mount. You should check first, if there is a thumbnail use thumbnail as a background image or wait until thumbnail load

0

I have got a new method of making this work. Basically I made a different component for rendering, and passed properties through props. I then used try and catch in the component where i map the array, and before sending the props, I try for error, if there's no error, it passes normally image links. if there's an error, I would pass image property as "", which basically means empty string in img tag. I will attach the code. its rough code, with console.logs, but main thing is inside the try and catch

main driver code

import React, { useEffect, useState } from 'react';
import Details from './bookDetails';
import './books.css'

export default function Books2() {

    const [bookName, setName] = useState("a");
    const [load, setLoad] = useState(false)
    const [itemArray, setArray] = useState([]);

    useEffect(() => {
        loadData();
    }, [])
    
    async function loadData() {
        setLoad(true);
        // console.log(bookName)
        await fetch("https://www.googleapis.com/books/v1/volumes?q=intitle:"+bookName)
            .then(response => response.json())
            .then(data => setArray(data.items))
        setLoad(false)
    }
    
    function handleChange(event) {
        // console.log(event.target.value)
        setName(event.target.value)
    }

    function handlePress() {
        loadData();
    }

    // console.log(itemArray)

    var className = (load===true) ? "loading" : "null"

    return (
        <div>
            <h1>Hello</h1>
            <input placeholder="book name" value={bookName} onChange={handleChange} />
            <button onClick={handlePress}>Search</button>
            <h3 className={className}>Loading...</h3>
            {/* <input placeholder="name of book" value={} /> */}
            {itemArray.map(book => {
                {/* console.log(book.volumeInfo.imageLinks) */}
                try{
                return(
                <Details 
                    key={book.id}
                    bookName={book.volumeInfo.title}
                    bookYear={book.volumeInfo.publishedDate}
                    bookDesc={book.volumeInfo.description}
                    bookLink={book.volumeInfo.infoLink}
                    bookImg={book.volumeInfo.imageLinks.smallThumbnail}
                />
                )}
                catch(err) {
                    <Details 
                    key={book.id}
                    bookName={book.volumeInfo.title}
                    bookYear={book.volumeInfo.publishedDate}
                    bookDesc={book.volumeInfo.description}
                    bookLink={book.volumeInfo.infoLink}
                    bookImg={""}
                />
                }
            })}
            {/* <button onClick={handlePress}>Search</button> */}
        </div>
    )
}

component for rendering code

import React from 'react';

export default function Details(props) {
    return(
        <div>
            <h1>{props.bookName}</h1>
            <a href={props.bookLink} target='_blank'>Link to book</a>

            <img src={props.bookImg} className="img"/>

            <h3>{props.bookYear}</h3>
            {/* <h4>{bookPage}</h4> */}
            {/* <h5>{bookRating}</h5> */}
            <p>{props.bookDesc}</p>
        </div>
    )
}