You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Ruby on Rails后端开发的JS前端更新书名时出现Undefined错误

Hey Carla, let's break down why you're hitting this Cannot read property 'renderUpdateForm' of undefined error and fix it step by step!

What's Causing the Error?

The core issues are a mix of botched event binding, unbuttoned button events, and type mismatch when looking up your Book instance:

1. You Overwrote Your handleEditClick Binding

In your App constructor, you accidentally replaced the bound handleEditClick with handleDeleteClick:

constructor() {
  this.adapter = new Adapter();
  this.handleEditClick = this.handleEditClick.bind(this);
  this.handleEditClick = this.handleDeleteClick.bind(this); // Oops! Overwrote the first binding
  // ... rest of your code
}

This meant when you clicked the "update" button, it was trying to run delete logic instead of edit logic.

2. All Buttons Trigger Both Edit and Delete Events

You attached both handleEditClick and handleDeleteClick to every <button> in the books list. No matter which button you clicked, both functions fired—creating chaos.

3. ID Type Mismatch Breaks findById

Your Book.id is a number (from your Rails API), but e.target.dataset.id returns a string. When you use === in findById, the type mismatch means it can't find the Book instance, returning undefined—hence the error when trying to call renderUpdateForm() on it.


Step-by-Step Fixes

1. Fix Event Binding in the App Constructor

Correct the binding so each handler gets its own bound version:

constructor() {
  this.adapter = new Adapter();
  this.handleEditClick = this.handleEditClick.bind(this);
  this.handleDeleteClick = this.handleDeleteClick.bind(this); // Bind delete handler separately
  this.handleFormSubmit = this.handleFormSubmit.bind(this);
  this.createBooks = this.createBooks.bind(this);
  this.createAuthors = this.createAuthors.bind(this);
  this.addBooks = this.addBooks.bind(this);
}

2. Distinguish Update/Delete Buttons

Add classes to your buttons so you can target them separately in your listener:

// In Book.renderListItem()
renderListItem() {
  return `
    <li>
      <h3>${this.title} - ${this.author} 
        <button data-id=${this.id} class="update-btn">update</button>
        <button data-id=${this.id} class="delete-btn">delete</button>
      </h3>
    </li>`;
}

Then update your event listeners to target specific buttons:

// In App.attachEventListeners()
attachEventListeners() {
  $('#books-list').on('click', '.update-btn', this.handleEditClick);
  $('#books-list').on('click', '.delete-btn', this.handleDeleteClick);
  $('#update').on('submit', 'form', this.handleFormSubmit);
}

3. Fix ID Type Mismatch

Convert the string ID to a number when looking up your Book instance. You can do this either in findById:

// In Book.findById()
static findById(id) {
  return this.all.find(book => book.id === parseInt(id));
}

Or directly in your handleEditClick and handleDeleteClick methods:

handleEditClick(e) {
  const id = parseInt(e.target.dataset.id);
  const book = Book.findById(id);
  $('#update').html(book.renderUpdateForm());
}

Bonus: Clean Up Delete Logic

Your delete function was sending unnecessary body data. Simplify it:

// In App.handleDeleteClick()
handleDeleteClick(e) {
  const id = parseInt(e.target.dataset.id);
  const book = Book.findById(id);
  this.adapter.deleteBook(book.id)
    .then(() => {
      // Remove the book from your array and refresh the list
      Book.all = Book.all.filter(b => b.id !== book.id);
      this.addBooks();
    });
}

// In Adapter.deleteBook()
deleteBook(id) {
  return this.delete(`${this.baseUrl}/books/${id}`);
}

delete(url) {
  return fetch(url, {
    method: 'DELETE',
    headers: this.headers
  }).then(res => res.json());
}

After making these changes, your update form should render correctly when you click the "update" button, and the error should be gone!

内容的提问来源于stack exchange,提问作者Carla Holcomb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:03:19