-1

So I have 3 functions below. One containing calls to the two (getBooks), which are getting requests. I set my state (isLoading) to true before the calls and then to true after the calls. This is to also make sure that the data is properly loaded. However the state is not updating so, therefore, my data from the get request is invalid. The callbacks in my setstate work in my other components, so I am confused. Below are my 3 functions.

import React from 'react';
import ReactDOM from 'react-dom';
import SidePane from './SidePane.js';
import HomeNavBar from './HomeNavBar.js';
import axios from 'axios';
import qs from 'qs';
import Loading from './Loading.js';

class HomePage extends React.Component {

    constructor(props) {
        super(props);
        this.state = { 
            bookSearch: "",
            bookSearchResults: [],
            bookSearchFound: false,
            isLoading: false
        };
        this.handleSearch = this.handleSearch.bind(this);
        this.alertBookName = this.alertBookName.bind(this);
        this.getBooksFromIsbn = this.getBooksFromIsbn.bind(this);
        this.getBooks = this.getBooks.bind(this);
        axios.defaults.withCredentials = true;
    }

    changeBookName = (e) => {

        var bookName = e.target.value;
        bookName = bookName.split(' ').join('+');
        this.setState({bookSearch: bookName})
    }

    getBooksFromIsbn(isbns){

        var books = [];

        axios
            .get('http://localhost:9000/api/getBooksFromIsbn',
            {
                params: {
                    books: JSON.stringify(isbns)
                }
            })
            .then(res =>
            {
                console.log(res.data);
                books = res.data;


            })
            .catch(error => {
                console.log(error.response);
            });
    }


    getBooks(){

        this.setState({
            isLoading: true
        },
            function(){console.log("setState completed", this.state)}
        );

        var bookResults = this.handleSearch();
        var books = this.getBooksFromIsbn(bookResults);

        this.setState({
            isLoading: false
        },
            function(){console.log("setState completed", this.state)}
        );
        this.props.setBookSearchResults(books);
    }


    handleSearch(){

        var bookResults = [];

        var url = 'http://localhost:9000/api/getOpenLibrarySearch';

        axios
        .get(url,
        {
            params: {
                bookSearch: this.state.bookSearch
            }
        })
        .then(res =>
        {
            //this.setState({bookSearchResults: res.data});

            for(var i=0; i < res.data.docs[i].isbn.length; i++){
                bookResults = bookResults.concat(res.data.docs[i].isbn);
            }
            console.log(bookResults);
        })
        .catch(error => {
            console.log(error.response);
        });

        return bookResults;
    }

    render(){

        if(this.state.isLoading == false){
            return(
                <div>
                    <HomeNavBar authToken = {this.props.authToken} email = {this.props.email} />
                    <SidePane changeBookName = {this.changeBookName} handleSearch = {this.getBooks} />
                </div>
            )           
        }
        else
        {
            return <Loading />;
        }

    }
}
IKnowMazin
  • 19
  • 2
  • 2
    "However the state is not updating" — Why do you expect it to update when you "change" it from `true` to `true`? – Quentin Apr 07 '20 at 07:56
  • 1
    Aside: `handleSearch` always returns an empty array and `getBooksFromIsbn` always returns `undefined`. – Quentin Apr 07 '20 at 07:57
  • Can you please show the entire component, Need to know when getBooks is called. Furthermore, if you can, please make working example in codesandbox. – Edwin Clement Apr 07 '20 at 08:02
  • @Quentin Sorry, I actually had both of them set to true just to see if it would change them because isLoading is defaulted to false. I updated my code above – IKnowMazin Apr 07 '20 at 15:33
  • @Quentin Could you give me some insight on how to not make them return as empty and undefined? – IKnowMazin Apr 07 '20 at 15:34
  • @EdwinClement Alright I updated my code above – IKnowMazin Apr 07 '20 at 15:35
  • https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Quentin Apr 07 '20 at 15:38

1 Answers1

0

It looks like you need to actually return the books value from getBooksFromIsbn. Await the axios call resolution and return books.

async getBooksFromIsbn (isbns) {
  const books = [];

  try {
    const res = await axios.get(
      'http://localhost:9000/api/getBooksFromIsbn',
      {
        params: {
          books: JSON.stringify(isbns)
        }
      });
    books = res.data;
  } catch(error) {
    console.log(error.response);
  }

  return books; 
}

Same for handleSearch, the code needs to wait and return the resolution of the GET request.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • I changed the functions to async and awaited both calls to handleSearch and getBooksFromIsbn however the books returned ends up being undefined – IKnowMazin Apr 07 '20 at 16:45