Пока я пытаюсь войти в React, я начал проект и застрял. Может быть, кто-то может помочь мне найти проблему. Ниже я объясню, что должно делать приложение.
Пользователь вводит запрос в поле ввода внутри SearchBar.jsx. Компонент SearchBar передает запрос в App.jsx и запускает функцию fetchPhotos, которая запускает запрос API.
Чтобы разобраться с разбиением на страницы, App.jsx импортирует Разбиение на страницы.jsx, который вычисляет количество изображений в ответе и отображает кнопки разбивки на страницы.
Выше работает.
Но теперь, если вы нажмете кнопку разбивки на страницы, значение страница из компонента разбивки на страницы должно быть передано в App.jsx и, следовательно, в функцию fetchPhotos (запускает запрос API).
Я предполагаю, что проблема в том, что значение страница никогда не попадает в App.jsx, поэтому в запросе API отсутствует значение page.
Я потратил часы, но не смог найти способ исправить это из-за недостатка знаний. Не могли бы вы указать мне правильное направление и показать мне, что не так с кодом?
App.jsx
import React, { Component } from "react";
import axios from "axios";
import Pagination from "../Pagination";
import SearchBar from "../SearchBar";
import ListItem from "../ListItem";
import "./app.scss";
class App extends Component {
state = {
photos: [],
totalPhotos: 0,
perPage: 30,
currentPage: 1,
query: null
};
componentDidMount() {
this.fetchPhotos("gorilla", this.state.currentPage);
}
fetchPhotos = (inputValue, page) => {
const baseUrl = "https://api.unsplash.com/search/photos";
const options = {
headers: {
Authorization: `Client-ID ${process.env.REACT_APP_UNSPLASH_API_KEY}`
},
params: {
query: inputValue,
page: this.state.page,
per_page: this.state.perPage
}
};
axios
.get(baseUrl, options)
.then(response => {
this.setState({
photos: response.data.results,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: page,
query: inputValue
});
})
.catch(() => {
console.info("Error");
});
};
render() {
return (
<div className = "app">
<SearchBar onSubmit = {this.fetchPhotos} />
<Pagination
current = {this.state.currentPage}
total = {this.state.totalPhotos}
perPage = {this.state.perPage}
query = {this.state.query}
onPageChanged = {query => this.fetchPhotos(this.state.query)}
/>
<List data = {this.state.photos} />
</div>
);
}
}
const List = ({ data }) => {
var items = data.map(photo => <ListItem key = {photo.id} photo = {photo} />);
return <div className = "grid">{items}</div>;
};
export default App;
SearchBar.jsx
import React, { Component } from "react";
class SearchBar extends Component {
state = {
inputValue: ""
};
handleFormSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.state.inputValue);
};
render() {
return (
<div className = "header">
<h1>Search for images on Unsplash</h1>
<form onSubmit = {this.handleFormSubmit} className = "ui form">
<input
type = "text"
placeholder = "Type here to search for images"
value = {this.state.inputValue}
onChange = {e => this.setState({ inputValue: e.target.value })}
/>
</form>
</div>
);
}
}
экспортировать SearchBar по умолчанию;
Разбиение на страницы.jsx
import React, { Component } from "react";
class Pagination extends Component {
pages() {
var pages = [];
for (var i = this.rangeStart(); i <= this.rangeEnd(); i++) {
pages.push(i);
}
return pages;
}
rangeStart() {
var start = this.props.current - this.props.pageRange;
return start > 0 ? start : 1;
}
rangeEnd() {
var end = this.props.current + this.props.pageRange;
var totalPages = this.totalPages();
return end < totalPages ? end : totalPages;
}
totalPages() {
return Math.ceil(this.props.total / this.props.perPage);
}
nextPage() {
return this.props.current + 1;
}
prevPage() {
return this.props.current - 1;
}
hasFirst() {
return this.rangeStart() !== 1;
}
hasLast() {
return this.rangeEnd() < this.totalPages();
}
hasPrev() {
return this.props.current > 1;
}
hasNext() {
return this.props.current < this.totalPages();
}
changePage(page) {
this.props.onPageChanged(page);
console.info("Page inside Pagination", page);
}
render() {
return (
<div className = "pagination">
<div className = "pagination__left">
<span
role = "button"
className = {!this.hasPrev() ? "hidden" : ""}
onClick = {e => this.changePage(this.prevPage())}
>
Prev
</span>
</div>
<div className = "pagination__mid">
<ul>
<li className = {!this.hasFirst() ? "hidden" : ""}>
<span role = "button" onClick = {e => this.changePage(1)}>
1
</span>
</li>
<li className = {!this.hasFirst() ? "hidden" : ""}>...</li>
{this.pages().map((page, index) => {
return (
<li key = {index}>
<span
role = "button"
onClick = {e => this.changePage(page)}
className = {this.props.current === page ? "current" : ""}
>
{page}
</span>
</li>
);
})}
<li className = {!this.hasLast() ? "hidden" : ""}>...</li>
<li className = {!this.hasLast() ? "hidden" : ""}>
<span
role = "button"
onClick = {e => this.changePage(this.totalPages())}
>
{this.totalPages()}
</span>
</li>
</ul>
</div>
<div className = "pagination__right">
<span
className = {!this.hasNext() ? "hidden" : ""}
onClick = {e => this.changePage(this.nextPage())}
>
Next
</span>
</div>
</div>
);
}
}
Pagination.defaultProps = {
pageRange: 2
};
export default Pagination;





Я думаю, что ваша ошибка связана с `onChange', потому что вы даете запрос текущего состояния для получения вместо нового запроса:
onPageChanged = {query => this.fetchPhotos(this.state.query)}
Вы должны заменить его на новый запрос, например:
onPageChanged = {query => this.fetchPhotos(query)}
РЕДАКТИРОВАТЬ 1:
Вы можете увидеть, как это работает на https://codesandbox.io/s/9ymjj8ko9p?fontsize=14.
Изменения, как я уже сказал, в App.jsx:
исправить свойство onPageChange для нумерации страниц, например:
onPageChanged = {page => this.fetchPhotos(this.state.query, page)}
ВАУ! Большое спасибо @Cespejo.