0

So I am building an application using react, and my list is not showing on render(). I have my parent component, and have a list of components, coming from SearchResult. Here is my code:

class CreateBookGroup extends Component {
  constructor(props) {
    super(props);

    this.state = {
      titleToSearch: "",
      searchResults: []
    }

  }

  new Promise((resolve, reject) => {
      let searchBook = this.searchFormatter();
      console.log("Search book is " + searchBook);
      searchForBook(searchBook, resolve, reject);
    }).then((res, err) => {
      if (err) {
        return console.error(err);
      }
      console.log(res.body);

      for (let i = 0; i < res.body.items.length; i++) {

        let smallThumbnail = null;

        if (res.body.items[i].volumeInfo.imageLinks) {
          smallThumbnail = res.body.items[i].volumeInfo.imageLinks.smallThumbnail;
        }

        let resultToAdd = {
          bookCover: smallThumbnail,
          bookTitle: res.body.items[i].volumeInfo.title,
          bookAuthors: res.body.items[i].volumeInfo.authors,
          bookDescription: res.body.items[i].volumeInfo.description
        }

        this.state.searchResults.push(resultToAdd);
      }



    });
  }

  render() {
    const searchBookRes = this.state.searchResults.map((result) => {
      <SearchResult
        bookCover={result.bookCover}
        bookTitle={result.bookTitle}
        authorName={result.bookAuthors}
        bookDescription={result.bookDescription}
        />
    });

    console.log(searchBookRes.length);

    return (
      <div className="GlobalAlignment">
        <Header/>
        <Container>
          <Row>
            <Col lg={12}>

              <h1>Create a group</h1>
              <div className="bookGroupDiv">

                <input
                  type="text"
                  className="searchText"
                  required
                  name="bookSearch"
                  onChange={this.handleChange.bind(this, "titleToSearch")}
                  placeholder="Search for a title"/>

                <button className="btnStandard searchBtn" onClick={this.searchGoogleBookApi.bind(this)}>Search</button>

              </div>

              {searchBookRes}
  ..................................

I have even tried to preset state, so that it looks like this when the page initially opens:

constructor(props) {
    super(props);

    this.state = {
      titleToSearch: "",
      searchResults: [{bookTitle: "Sample", bookCover: "Cover", bookAuthors: "Author", bookDescription: "This is the description"}]
    }

  }

However, the {searchBookRes} still does not show any of my list items, even though they appear when I log them to the console.

Also, I have manually entered in test values into my child component, and placed it directly into the Component like this (This passes down props just fine):

return (
      <div className="GlobalAlignment">
        <Header/>
        <Container>
          <Row>
            <Col lg={12}>

              <h1>Create a group</h1>
              <div className="bookGroupDiv">

                <input
                  type="text"
                  className="searchText"
                  required
                  name="bookSearch"
                  onChange={this.handleChange.bind(this, "titleToSearch")}
                  placeholder="Search for a title"/>

                <button className="btnStandard searchBtn" onClick={this.searchGoogleBookApi.bind(this)}>Search</button>

              </div>

              <SearchResult
                 bookCover={'Test cover'}
                 bookTitle={'test title'}
                 authorName={'test author'}
                 bookDescription={'test description'}
    />

So since this passes down props fine, and shows component, I know there is not a problem with the SearchResult component. Does anyone see what I could be doing wrong? I am returning to react after a long time away, and can't figure out why this issue is occurring. Thank you for the help.

1 Answer 1

2

You are not returning anything inside the map body, Write it like this:

const searchBookRes = this.state.searchResults.map((result) => {
      return <SearchResult
                 bookCover={result.bookCover}
                 bookTitle={result.bookTitle}
                 authorName={result.bookAuthors}
                 bookDescription={result.bookDescription}
             />
});

Never mutate the state value directly, so instead of this.state.searchResults.push(resultToAdd), first create a local variable do the changes in that then use setState to update the state value, like this:

let values = this.state.searchResults.slice();
for (let i = 0; i < res.body.items.length; i++) {
    let smallThumbnail = null;

    if (res.body.items[i].volumeInfo.imageLinks) {
        smallThumbnail = res.body.items[i].volumeInfo.imageLinks.smallThumbnail;
    }

    let resultToAdd = {
        bookCover: smallThumbnail,
        bookTitle: res.body.items[i].volumeInfo.title,
        bookAuthors: res.body.items[i].volumeInfo.authors,
        bookDescription: res.body.items[i].volumeInfo.description
    }

    values.push(resultToAdd);;
}

this.setState({searchResults: values});
Sign up to request clarification or add additional context in comments.

1 Comment

Ahhh, such a simple mistake. And thank you for the advice on mutating state as well.

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.