在视图中追加新项目

时间:2020-08-03 05:50:07

标签: javascript reactjs

我创建了一个图片搜索应用,其中当前显示9张图片。我想要一个加载更多按钮,单击该按钮可在现有9张图像下方显示另外9张图像。现在,当我单击“加载更多”按钮时,它确实显示新的9张图像,但之前的9张图像消失了。单击加载更多时,如何显示所有图像

App.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";

export default class App extends Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
    this.fetchPhotos = this.fetchPhotos.bind(this);
    this.state = {
      photos: [],
      totalPhotos: 0,
      perPage: 5,
      currentPage: 1,
      loadState: LOAD_STATE.LOADING,
      search: ""
    };
  }
  handleChange(e) {
    this.setState({ search: e.target.value });
  }

  componentDidMount() {
    this.fetchPhotos(this.state.currentPage);
  }

  fetchPhotos(page = 1) {
    var self = this;
    const { search, perPage } = this.state;
    const url1 = `https://api.unsplash.com/photos?page=${page}&client_id=${appId}`;
    const url2 =
      `https://api.unsplash.com/search/photos?page=${page}&query=` +
      search +
      "&client_id=" +
      appId;
    const url = search ? url2 : url1;

    if (search) {
      const options = {
        params: {
          page: page,
          per_page: perPage,
          order_by: "popularity"
        }
      };

      this.setState({ loadState: LOAD_STATE.LOADING });
      axios
        .get(url, options)
        .then(response => {
          this.setState({
            photos: response.data.results,
            totalPhotos: parseInt(response.headers["x-total"]),
            currentPage: page,
            loadState: LOAD_STATE.SUCCESS
          });
        })
        .catch(() => {
          this.setState({ loadState: LOAD_STATE.ERROR });
        });
    } else {
      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 });
        });
    }
  }

  render() {
    return (
      <div className="app">
        <input
          onChange={this.handleChange}
          type="text"
          name="search"
          placeholder="Enter query"
        />
        <button
          type="submit"
          onClick={() => this.fetchPhotos(1)}
          className="button"
        >
          Submit
        </button>

        {this.state.loadState === LOAD_STATE.LOADING ? (
          <div className="loader" />
        ) : (
          <List data={this.state.photos} />
        )}
        <Pagination
          current={this.state.currentPage}
          total={this.state.totalPhotos}
          perPage={this.state.perPage}
          onPageChanged={this.fetchPhotos.bind(this)}
        />
      </div>
    );
  }
}

List.js

import React from "react";
import ListItem from "./ListItem";
const List = ({ data }) => {
  var items = data.map(photo => <ListItem key={photo.id} photo={photo} />);
  return <div className="grid">{items}</div>;
};

export default List;

Pagination.js

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__right">
          <a
            href="#"
            className={!this.hasNext() ? "hidden" : ""}
            onClick={e => this.changePage(this.nextPage())}
          >
            Load More
          </a>
        </div>
      </div>
    );
  }
}

Pagination.defaultProps = {
  pageRange: 2
};

1 个答案:

答案 0 :(得分:1)

问题是您用新的响应覆盖了当前的photos状态。您必须将响应附加到您现有的photos状态

axios
    .get(url, options)
    .then(response => {
        self.setState({
            photos: [...this.state.photos, ...response.data], // using spread syntax
            ...
        });
    })
...