Preface: I'm still getting used to ES6 and working on my first React App via an online class. I'll share my issue here and my git repository for anyone who's willing to dig into it. The app allows you to search and organize books in different categories.
The error:
Uncaught (in promise) TypeError: Cannot read property 'forEach' of undefined
at Object.mergeShelfAndSearch (BookUtils.js:22)
at Search.js:41
BookUtils.js
exports a couple of functions to React components (not sure how it knows where to go, but it works). The Search.js
component handles the search functionality. While testing I'll search for something that doesn't exist(i.e 'zzzzz'). When I type something that I know exists I get the error above.
Code in BookUtils.js
:
export const mergeShelfAndSearch = (shelf, search) => {
const hashTable = {};
shelf.forEach(book => hashTable[book.id] = book.shelf);
search.forEach(book => {
book.shelf = hashTable[book.id] || 'none';
});
return search;
}
The error being the 'shelf.forEach'.
Code in Search.js :
updateSearch = () => {
if (this.state.query === "") {
this.setState({ error: false, books: [] });
return;
}
BooksAPI.search(this.state.query).then(response => {
let newList = [];
let newError = false;
if (response === undefined || (response.error && response.error !== "empty query")) {
newError = true;
} else if (response.length) {
newList = BookUtils.mergeShelfAndSearch(this.props.selectedBooks, response);
newList = BookUtils.sortAllBooks(newList);
}
this.setState({ error: newError, books: newList });
})
}
Error is in the else if statement with ''mergeShelfAndSearch' from BookUtils.js
. I've tried setting 'shelf' as a global var and still get errors and I feel like I've put console.log(shelf); everywhere without any luck. Below is a link to my repo if any one is curios enough. Thanks!
https://github.com/alecb513/reactnd-project-myreads-starter-master
Change
else if (response.length) {
newList = BookUtils.mergeShelfAndSearch(this.props.selectedBooks, response);
newList = BookUtils.sortAllBooks(newList);
}
To
else if (response.length) {
newList = BookUtils.mergeShelfAndSearch(Array.isArray(this.props.selectedBooks) ? this.props.selectedBooks: [], response);
newList = BookUtils.sortAllBooks(newList);
}
Or
else if (response.length && Array.isArray(this.props.selectedBooks)) {
newList = BookUtils.mergeShelfAndSearch(Array.isArray( this.props.selectedBooks, response);
newList = BookUtils.sortAllBooks(newList);
The reason you get .forEach is undefined because initially this.props.selectedBooks might be undefined or null or an object. So doing .forEach on it will throw you an error. So to fix the issue check if it is an array or not and before passing this.props.selectedBooks to mergeShelfAndSearch function. Also make sure you send array of data to selectedBooks from parent component