Я строю проект на основе React для учебных целей. Я застрял в создании компонента таблицы, который отображает себя, а затем отправляет запрос ajax в бэкэнд mbaas, чтобы получить все записи в книге и заполнить каждый в новой строке. Вот что я нашел до сих пор. Пожалуйста, простите большой кусок кода, но так как я еще не в полной мере понять взаимодействие между методами, состояния и визуализации() здесь весь класс:Реагировать на проблемы компонентов с состоянием, setState и рендером
class BooksTable extends Component {
constructor(props) {
super(props);
this.state = {
books: []
};
this.updateState = this.updateState.bind(this);
this.initBooks = this.initBooks.bind(this);
}
componentDidMount() {
let method = `GET`;
let url = consts.serviceUrl + `/appdata/${consts.appKey}/${consts.collection}`;
let headers = {
"Authorization": `Kinvey ${sessionStorage.getItem(`authToken`)}`,
"Content-Type": `application/json`
};
let request = {method, url, headers};
$.ajax(request)
.then(this.initBooks)
.catch(() => renderError(`Unable to connect. Try again later.`));
}
deleteBook(id) {
let method = `DELETE`;
let url = consts.serviceUrl + `/appdata/${consts.appKey}/${consts.collection}/${id}`;
let headers = {
"Authorization": `Kinvey ${sessionStorage.getItem(`authToken`)}`,
"Content-Type": `application/json`
};
let request = {method, url, headers};
$.ajax(request)
.then(() => this.updateState(id))
.catch(() => renderError(`Unable to delete, something went wrong.`));
}
updateState(id) {
for (let entry of this.state.books.length) {
if (entry.id === id) {
// Pretty sure this will not work, but that is what I've figured out so far.
this.state.books.splice(entry);
}
}
}
initBooks(response) {
console.log(`#1:${this.state.books});
console.log(`#2:${this});
for (let entry of response) {
this.setState({
books: this.state.books.concat([{
id: entry._id,
name: entry.name,
author: entry.author,
description: entry.description,
price: Number(entry.name),
publisher: entry.publisher
}])
},() => {
console.log(`#3${this.state.books}`);
console.log(`#4${this}`);
});
}
}
render() {
return (
<div id="content">
<h2>Books</h2>
<table id="books-list">
<tbody>
<tr>
<th>Title</th>
<th>Author</th>
<th>Description</th>
<th>Actions</th>
</tr>
{this.state.books.map(x =>
<BookRow
key={x.id}
name={x.name}
author={x.author}
description={x.description}
price={x.price}
publisher={x.publisher} />)}
</tbody>
</table>
</div>
);
}
}
Теперь BookRow не очень интересно, только часть onClick актуальна. Это выглядит так:
<a href="#" onClick={() => this.deleteBook(this.props.id)}>{owner? `[Delete]` : ``}</a>
Ссылка не должна быть видимой, если вошедший в систему пользователь не является издателем книги. onClick вызывает deleteBook (id), который является методом из BookTable. При успешном ajax он должен удалить книгу из state.books (array) и render.
Меня особенно смущает метод initBooks. Я добавил журналы перед циклом, который заполняет состояние и вызывает обратные вызовы при обновлении состояния. Результаты из журнала №1 и журнала №3 идентичны, для журналов № 2 # 4. Также, если я разворачиваю log # 2 (до setState) или log # 4, оба из них показывают состояние = [1]. Как это имеет смысл? Кроме того, если вы посмотрите журналы # 1 # 3 - они печатают []. Вероятно, мне не хватает взаимодействия с внутренними компонентами, но я действительно не могу понять, что.
Спасибо.
SetState действия являются асинхронными, так что изменения могут быть не отражены в this.state сразу. –