我正在重构一个小型应用程序,将书籍组织到各自的货架上。我已将JSX
提取到Book.js
文件中以处理每个图书对象的呈现,并调用updateShelf
方法在书架之间移动图书。
为此,我已从updateShelf
导出App.js
函数,并将其导入Book.js
组件中,该组件嵌入ListBooks
中map
使用Book
函数将每个图书对象传递给onChange
进行渲染。
我遇到的问题是当Book
中的TypeError: Object(...) is not a function
处理程序触发时,我得到以下异常:
17 | <div className="book-top">
18 | <div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
19 | <div className="book-shelf-changer">
> 20 | <select value={book.shelf} onChange={(e) => updateShelf(book, e.target.value)}>
21 | <option value="none" disabled >Move to...</option>
22 | <option value="currentlyReading" >Currently Reading</option>
23 | <option value="wantToRead" >Want to Read</option>
App.js
我不确定我做错了什么。
我已经包含了很多内容,因为我不确定问题源的确切位置。如果我需要减少帖子,请告诉我。
import React, { Component } from 'react'
import ListBooks from './ListBooks'
import SearchBooks from './SearchBooks'
import * as BooksAPI from './utils/BooksAPI'
import { Route } from 'react-router-dom'
class BooksApp extends Component {
state = {
books: []
}
componentDidMount() {
BooksAPI.getAll()
.then((books) => {
this.setState(() => ({
books
}))
})
}
updateShelf(book, shelf) {
this.state.books.forEach(b => {
if(b.id === book.id && shelf !== '' && shelf !== 'none') {
b.shelf = shelf
this.setState((currentState) => ({
books: currentState.books
}))
BooksAPI.update(book, shelf)
}
});
}
render() {
return (
<div>
<Route exact path='/' render={() => (
<ListBooks
books={this.state.books}
onUpdateShelf={this.updateShelf}
/>
)} />
<Route exact path='/search' render={() => (
<SearchBooks
books={this.state.books}
/>
)} />
</div>
)
}
}
export default BooksApp
export const updateShelf = updateShelf;
ListBooks.js
import React, { Component } from 'react';
import PropTypes from 'prop-types'
import './App.css'
import { Link } from 'react-router-dom'
import Book from './Book'
const shelves = [
{
key: 'currentlyReading',
name: 'Currently Reading'
},
{
key: 'wantToRead',
name: 'Want To Read'
},
{
key: 'read',
name: 'Read'
}
];
class ListBooks extends Component {
static propTypes = {
books: PropTypes.array.isRequired
}
render() {
const { books } = this.props
function getBooksForShelf(shelfKey) {
return books.filter(book => book.shelf === shelfKey);
}
return(
<div className="app">
<div className="list-books">
<div className="list-books-title">
<h1>My Reads</h1>
</div>
<div className="list-books-content">
<div>
{ shelves.map((shelf) => (
<div key={shelf.key} className="bookshelf">
<h2 className="bookshelf-title">{shelf.name}</h2>
<div className="bookshelf-books">
<ol className="books-grid">
<li>
{ getBooksForShelf(shelf.key).map((book) => (
<Book key={book.id} book={book}/>
))}
</li>
</ol>
</div>
</div>
)) }
</div>
</div>
<Link
to='/search'
className="open-search">
Find a Book
</Link>
</div>
}
</div>
)
}
}
export default ListBooks
Book.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { updateShelf } from './App'
class Book extends Component {
static propTypes = {
book: PropTypes.object.isRequired
}
render() {
const { book } = this.props
return(
<div key={book.id} className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
<div className="book-shelf-changer">
<select value={book.shelf} onChange={(e) => updateShelf(book, e.target.value)}>
<option value="none" disabled >Move to...</option>
<option value="currentlyReading" >Currently Reading</option>
<option value="wantToRead" >Want to Read</option>
<option value="read" >Read</option>
<option value="none" >None</option>
</select>
</div>
</div>
<div className="book-title">{book.title}</div>
<div className="book-authors">{book.authors}</div>
</div>
)
}
}
export default Book
{{1}}
答案 0 :(得分:1)
您正在导出export const updateShelf = updateShelf
。但updateShelf
是组件的一部分,因此很可能未定义。如果您计划导出该方法,则应将该方法移出该类,或者如果您希望更改该组件,则将该方法作为prop传递。