[英]displaying search query results in all pages
我使用 unsplash api 制作了一个图像搜索应用程序。 该应用程序包含分页,这就是问题所在。 当我搜索诸如花之类的东西时,它会在第一页显示花,但是当我将 go 转到第二页时,不再有花,而是由 componentDidMount 中的 fetchPhotos function 生成的默认照片,因为重新渲染我相信。 有没有一种方法可以让我在刷新页面之前查看所有页面中的搜索查询结果?
应用程序.js
import React, { Component } from "react";
import Pagination from "./Pagination";
import List from "./List";
import "./styles.css";
import axios from "axios";
const LOAD_STATE = {
SUCCESS: "SUCCESS",
ERROR: "ERROR",
LOADING: "LOADING"
};
const appId = "N1ZIgf1m1v9gZJhledpAOTXqS8HqL2DuiEyXZI9Uhsk";
const BASE_URL = "https://api.unsplash.com/photos?page=1";
export default class App extends Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
photos: [],
totalPhotos: 0,
perPage: 5,
currentPage: 1,
loadState: LOAD_STATE.LOADING,
search: ""
};
}
handleChange(e) {
this.setState({ search: e.target.value });
}
handleSubmit() {
const { search, perPage } = this.state;
console.log(search);
const url =
"https://api.unsplash.com/search/photos?page=1&query=" +
search +
"&client_id=" +
appId;
const options = {
params: {
client_id: appId,
page: 1,
per_page: perPage,
order_by: "popularity"
}
};
this.setState({ loadState: LOAD_STATE.LOADING });
axios
.get(url, options)
.then(response => {
console.log(typeof response.data);
let photos;
try {
photos = response.data.results;
} catch {
photos = [];
}
this.setState({
photos,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: 1,
loadState: LOAD_STATE.SUCCESS
});
})
.catch(() => {
this.setState({ loadState: LOAD_STATE.ERROR });
});
}
componentDidMount() {
this.fetchPhotos(this.state.currentPage);
}
fetchPhotos(page) {
var self = this;
const { perPage } = this.state;
const options = {
params: {
client_id: appId,
page: page,
per_page: perPage,
order_by: "popularity"
}
};
this.setState({ loadState: LOAD_STATE.LOADING });
axios
.get(BASE_URL, options)
.then(response => {
self.setState({
photos: response.data,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: page,
loadState: LOAD_STATE.SUCCESS
});
})
.catch(() => {
this.setState({ loadState: LOAD_STATE.ERROR });
});
}
render() {
return (
<div className="app">
<input
onChange={this.handleChange}
type="text"
name="search"
placeholder="Enter query"
/>
<button type="submit" onClick={this.handleSubmit} className="button">
Submit
</button>
<Pagination
current={this.state.currentPage}
total={this.state.totalPhotos}
perPage={this.state.perPage}
onPageChanged={this.fetchPhotos.bind(this)}
/>
{this.state.loadState === LOAD_STATE.LOADING ? (
<div className="loader" />
) : (
<List data={this.state.photos} />
)}
</div>
);
}
}
分页
import React, { Component } from "react";
export default 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);
}
render() {
return (
<div className="pagination">
<div className="pagination__left">
<a
href="#"
className={!this.hasPrev() ? "hidden" : ""}
onClick={e => this.changePage(this.prevPage())}
>
Prev
</a>
</div>
<div className="pagination__mid">
<ul>
<li className={!this.hasFirst() ? "hidden" : ""}>
<a href="#" onClick={e => this.changePage(1)}>
1
</a>
</li>
<li className={!this.hasFirst() ? "hidden" : ""}>...</li>
{this.pages().map((page, index) => {
return (
<li key={index}>
<a
href="#"
onClick={e => this.changePage(page)}
className={this.props.current == page ? "current" : ""}
>
{page}
</a>
</li>
);
})}
<li className={!this.hasLast() ? "hidden" : ""}>...</li>
<li className={!this.hasLast() ? "hidden" : ""}>
<a href="#" onClick={e => this.changePage(this.totalPages())}>
{this.totalPages()}
</a>
</li>
</ul>
</div>
<div className="pagination__right">
<a
href="#"
className={!this.hasNext() ? "hidden" : ""}
onClick={e => this.changePage(this.nextPage())}
>
Next
</a>
</div>
</div>
);
}
}
Pagination.defaultProps = {
pageRange: 2
};
问题在这里:
onPageChanged={this.fetchPhotos.bind(this)}
因为fetchPhotos
不使用任何类型的查询来获取特定类型的照片,所以当页面更改时,您会得到默认响应。
您目前有两个功能可用于获取工作方式不同的照片。 您需要将代码重构为使用来自 state 的当前query
的单个照片获取 function。
更新
像这样的东西:
fetchPhotos(page=1) {
var self = this;
const { search, perPage } = this.state;
const url = `https://api.unsplash.com/search/photos?page=${page}&client_id=${appId}`
const url = search ? `${url}&query=search` : url
const options = {
params: {
client_id: appId,
page: page,
per_page: perPage,
order_by: "popularity"
}
};
this.setState({ loadState: LOAD_STATE.LOADING });
axios
.get(url, options)
.then(response => {
self.setState({
photos: response.data,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: page,
loadState: LOAD_STATE.SUCCESS
});
})
.catch(() => {
this.setState({ loadState: LOAD_STATE.ERROR });
});
}
然后你可以在 mount 上调用fetchPhotos
并使用它来代替你的onSubmit
,看起来你可以摆脱它。
<button type="submit" onClick={this.fetchPhotos} className="button">
Submit
</button>
您的onPageChanged
会获得一个 function 来获取默认照片。 您拥有的唯一一个基于动态输入/状态获取照片的 function 在您的handleSubmit
中。 将handleSubmit
的主体提取到另一个变量中的箭头 function 中,并在 handleSubmit 中调用这个新提取的handleSubmit
同时将这个新的 ZC1C425268E68385D1AB5074C17A94F14 传递给onPageChanged
。 在handleSubmit
和onPageChanged
中留下相同的 API 调用
由于您使用的是 class 组件,因此将handleSubmit
的主体提取为常量可能不是一个好主意。
而是将您的fetchPhotos
方法重命名为fetchDefaultPhotos
并将您的handleSubmit
方法重命名为fetchPhotos
以更好地表示每个方法的作用。
将新重命名的fetchPhotos
给onPageChanged
并在您的componentDidMount
中调用fetchDefaultPhotos
。 您还可以创建一个新的handleSubmit
方法,该方法仅在需要时调用fetchPhotos
。
export default class App extends Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
photos: [],
totalPhotos: 0,
perPage: 5,
currentPage: 1,
loadState: LOAD_STATE.LOADING,
search: ""
};
}
handleChange(e) {
this.setState({ search: e.target.value });
}
handleSubmit(newPage) {
this.fetchPhotos(newPage)
}
fetchPhotos(newPage) {
const { search, perPage } = this.state;
console.log(search);
const url =
"https://api.unsplash.com/search/photos?page=1&query=" +
search +
"&client_id=" +
appId;
const options = {
params: {
client_id: appId,
page: 1,
per_page: perPage,
order_by: "popularity"
}
};
this.setState({ loadState: LOAD_STATE.LOADING });
axios
.get(url, options)
.then(response => {
console.log(typeof response.data);
let photos;
try {
photos = response.data.results;
} catch {
photos = [];
}
this.setState({
photos,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: newPage,
loadState: LOAD_STATE.SUCCESS
});
})
.catch(() => {
this.setState({ loadState: LOAD_STATE.ERROR });
});
}
componentDidMount() {
this.fetchDefaultPhotos(this.state.currentPage);
}
fetchDefaultPhotos(page) {
var self = this;
const { perPage } = this.state;
const options = {
params: {
client_id: appId,
page: page,
per_page: perPage,
order_by: "popularity"
}
};
this.setState({ loadState: LOAD_STATE.LOADING });
axios
.get(BASE_URL, options)
.then(response => {
self.setState({
photos: response.data,
totalPhotos: parseInt(response.headers["x-total"]),
currentPage: page,
loadState: LOAD_STATE.SUCCESS
});
})
.catch(() => {
this.setState({ loadState: LOAD_STATE.ERROR });
});
}
}
更新:
这是一个工作沙箱: https://codesandbox.io/s/so-op-sbx-6rnhu
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.