私は
App.js
の機能を持つ基本的なReactアプリを持っています棚間での本の移動を処理する後続のコンポーネントの小道具として受け渡すコンポーネント。
関数を1レベル下に渡すと、
App.js
から
ListBooks.js
へ
Books.js
に渡されるユーザーが新しいシェルフを選択し、API呼び出しと状態の更新をトリガーするコンポーネントです。これは正常に機能します。
しかし、その後
App.js
から同じことをしようとすると>
SearchBooks.js
>
Book.js
動作していないようです。
私が期待しているのは、
updateShelf
ブックと状態を更新するために呼び出される関数。
「コードの壁」が多すぎる場合はおologiesび申し上げます。問題がどこにあるのか正確にはわかりません。
編集:
コメントで示唆されているように、CodeSandboxのバージョンは次のとおりです。 https://codesandbox.io/s/github/richardcurteis/myreads-udacity
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) {
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
onUpdateShelf={this.updateShelf}
/>
)} />
</div>
)
}
}
export default BooksApp
SearchBooks.js
import React, { Component } from 'react'
import * as BooksAPI from './utils/BooksAPI'
import Book from './Book';
export default class SearchBooks extends Component {
state = {
query: '',
books: []
}
updateQuery(query) {
this.setState(() => ({
books: [],
query: query
}))
this.bookSearch(query)
}
bookSearch(e) {
if (e.length > 0) BooksAPI.search(e)
.then(books => this.setState(currentState => ({
books: books
})));
}
render() {
const { query, books } = this.state
const { onUpdateShelf } = this.props
return(
<div className="search-books">
<div className="search-books-bar">
<a className="close-search" >Close</a>
<div className="search-books-input-wrapper">
<input
type="text"
placeholder="Search by title, author or subject"
value={query}
onChange={(event) => this.updateQuery(event.target.value)}
/>
</div>
</div>
<div className="search-books-results">
<ol className="books-grid">
<li>
{ !books.error ? (
books.map((book) => (
<Book
key={book.id}
book={book}
updateShelf={onUpdateShelf}
/>
))
) : (
<h4>"{query}", is not a valid search</h4>
)}
</li>
</ol>
</div>
</div>
)
}
}
Book.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Book extends Component {
static propTypes = {
book: PropTypes.object.isRequired
}
render() {
const { book, updateShelf } = 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 ? book.shelf : 'none'} onChange={(e) => updateShelf(book, e.target.value)}>
<option 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
参考のために:
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,
onUpdateShelf: PropTypes.func.isRequired
}
render() {
const { books, onUpdateShelf } = 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>
{ getBooksForShelf(shelf.key).length === 0 ? (
<div>
<h4>No books in this shelf</h4>
</div>
) : (
<div className="bookshelf-books">
<ol className="books-grid">
<li>
{ getBooksForShelf(shelf.key).map((book) => (
<Book key={book.id}
book={book}
updateShelf={onUpdateShelf}/>
))}
</li>
</ol>
</div>
)}
</div>
)) }
</div>
</div>
<Link
to='/search'
className="open-search">
Find a Book
</Link>
</div>
</div>
)
}
}
export default ListBooks
回答 1 件
関連記事
- 反応ネイティブのアラートボタンから関数に値を渡す方法
- React Ref:オブジェクトの配列のRef関数は、最初のアイテムのみをログに記録します
- React Hookは、React関数コンポーネントでもカスタムReactHook関数でもない関数で呼び出されます
- react jsでエフェクト関数を使用すると、正常に動作している間にインポートするように指示されます
- 反応:Datatablesの各行のボタンにonclick関数を追加する方法
- 反応関数コンポーネントのsetStateが状態を更新していません
- useEffectmapは関数ではありませんReactHooks
- Reactステートレスコンポーネント内で関数を定義しても大丈夫ですか?
- フックuseStateに反応するように関数を設定するより良い方法はありますか?
- Modalで関数を渡すときに、ReactNativeの「onPressは関数ではありません」
議論したように、それは小道具の受け渡しの問題ではなく、状態の更新の問題です。動作しているように見える変更されたコードは次のとおりです。
または状態を変更せずに良い: