Я начал изучать реагирование на прошлой неделе.Я создаю приложение реагирования, которое управляет цитатами книг по названиям книг и авторам.Я разработал компоненты реакции на странице книг следующим образом:
Компонент Books является родительским для компонентов NewBook и BookList.Я использую state
в Книгах и NewBook.Один для массива книг и другой для добавления новой книги.Я хочу обновить состояние из книг (родительский) в NewBook (дочерний), вызвав addBook (функцию) из родительского объекта, переданного в качестве опоры дочернему элементу.Но у меня есть проблема, когда состояние родителя в функции addBook переопределяется.
Books.js
import React from "react";
import { BookList } from "./BookList";
import { NewBook } from "./NewBook";
export class Books extends React.Component {
constructor() {
super();
this.state = {
books: [
{title: "The Black Swan", author: "Nassim Nicholas Taleb"},
{title: "The Lean Startup", author: "Eric Ries"}
]
};
}
addBook(title, author) {
console.log("adding..");
const newBooks = this.state.books;
newBooks.push({title: title, author: author});
this.setState({
books: newBooks
});
}
render() {
return (
<div className="col-md-6 offset-3">
<NewBook onAdd={this.addBook} defaultTitle={''} defaultAuthor={''} />
<BookList books={this.state.books}/>
</div>
);
}
}
NewBook.js
import React from "react";
export class NewBook extends React.Component {
constructor(props) {
super();
this.state = {
title: props.defaultTitle,
author: props.defaultAuthor
};
}
add() {
this.props.onAdd(this.state.title, this.state.author);
this.setState({title: this.props.defaultTitle, author: this.props.defaultAuthor});
}
updateTitle(event) {
this.setState({title: event.target.value});
}
updateAuthor(event) {
this.setState({author: event.target.value});
}
render() {
return (
<div>
<div className="form-group">
<textarea
className="form-control col-md-12"
rows="2" placeholder="I am reading this book named"
value={this.state.title}
onChange={(event) => this.updateTitle(event)} />
</div>
<div className="form-group">
<label htmlFor="author" className="font-italic font-weight-light">by</label>
<input className="form-control form-control-sm col-md-12"
id="author" placeholder="this author"
value={this.state.author}
onChange={(event) => this.updateAuthor(event)}/>
</div>
<div className="form-group">
<button disabled={this.state.title === '' || this.state.author === ''} onClick={() => this.add()} className="btn btn-primary btn-lg btn-block">Add</button>
</div>
</div>
);
} }
BookList.js (нетпроблема в этом компоненте)
import React from "react";
import { Link } from "react-router-dom";
export class BookList extends React.Component {
render() {
var books = this.props.books;
return (
<ul>
{books.map((item, i) => <li key={i}><Link to={{ pathname: "/quotes", search: "?title=" + item.title }}>{item.title}</Link> by <Link to={{ pathname: "/quotes", search: "?author=" + item.author }}>{item.author}</Link></li>)}
</ul>
);
}
}
Когда я нажимаю кнопку Добавить, я получаю сообщение об ошибке
adding..
Uncaught TypeError: Cannot read property 'books' of undefined
at Object.addBook [as onAdd] (Books.js:44)
at NewBook.add (NewBook.js:40)
at onClick (NewBook.js:93)
at HTMLUnknownElement.callCallback (react-dom.development.js:104)
at Object.invokeGuardedCallbackDev (react-dom.development.js:142)
at Object.invokeGuardedCallback (react-dom.development.js:191)
at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:205)
at executeDispatch (react-dom.development.js:470)
at executeDispatchesInOrder (react-dom.development.js:492)
at executeDispatchesAndRelease (react-dom.development.js:590)
Этот новичок что-то пропустил?Кстати, я использую
"react": "^16.3.1",
"react-dom": "^16.3.1",