Calling class method within a prefix returns: Uncaught (in Promise) Typeerror: _this3.updateShelvesState is not a Function

Asked

Viewed 296 times

1

Good Afternoon!

I created a method called updateShelvesState which is called before the component is rendered, and onChange of another component called Book.

This method takes an array and creates a new array organized by the key shelf of each object that exists within the array.

When rendering the page, when I call the method within componentDidMount, everything goes well.

But by using the same method within a onChange subcomponent Book, I get the following error:

Uncaught (in promise) TypeError: _this3.updateShelvesState is not a function

The function getAll only returns API data.

Follows code:

import React, { Component } from "react";
import "./../App.css";
import { Link } from "react-router-dom";
import { getAll, update } from "../BooksAPI";
import Book from "./../components/Book";

class BookContainer extends Component {
  state = {
    shelves: []
  }

  componentDidMount() {
    getAll()
      .then(books => this.updateShelvesState(books))
      .catch(error => console.log(error));
  }

  updateShelvesState(books) {
    const booksGroupByShelf = books.reduce((newObj, book) => {
      newObj[book.shelf] = newObj[book.shelf] || [];
      newObj[book.shelf].push(book);
      return newObj;
    }, {})

    const shelves = Object.keys(booksGroupByShelf).map(key => {
      return { group: key, items: booksGroupByShelf[key] };
    });
    this.setState({ shelves });

  }


  onChangeShelf(book, shelf) {
    update(book, shelf)
     .then(getAll)
     .then(data => this.updateShelvesState(data) )    
  }

  render() {
    const { shelves } = this.state;

    return (
      <div className="app">
        <div className="list-books">
          <div className="list-books-title">
            <h1>MyReads</h1>
          </div>
          <div className="list-books-content">
            <div>
              {shelves.map((shelf, index) => {
                return (
                  <div key={index} className="bookshelf">
                    <h2 className="bookshelf-title">{shelf.group}</h2>
                    <div className="bookshelf-books">
                      {shelf.items.length > 0 && (
                        <ol className="books-grid">
                          {shelf.items.map(item => (
                            <Book
                              key={item.id}
                              book={item}
                              onChangeShelf={this.onChangeShelf}
                            />
                          ))}
                        </ol>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
          <div className="open-search">
            <Link to="/search">Add a book</Link>
          </div>
        </div>
      </div>
    );
  }
}

export default BookContainer;

Thank you for your attention

1 answer

1


You must bind to the class you are in, so the method runs in the right context/this.

Mute

onChangeShelf={this.onChangeShelf}

for

onChangeShelf={this.onChangeShelf.bind(this)}
  • 1

    Beauty @Sergio, thank you!

  • @Alinevianna of nothing

Browser other questions tagged

You are not signed in. Login or sign up in order to post.