将每次获取的新搜索结果替换为react-infinite-scroll-component中的搜索结果

问题描述 投票:3回答:2

[在此应用中,我正在从Unsplash API(具有Express后端,React前端)中获取图像。在页面加载时,将显示常规图像(在react-infinite-scroll-component内部渲染)。如果您搜索术语,则search状态将从false变为true。我使用三元运算符有条件地在无限滚动组件中渲染图像:

{this.state.newSearch || this.state.search ? this.state.searchImages.map(image =>
          <Image key={image.id} image={image} />
        ) : this.state.images.map(image =>
          <Image key={image.id} image={image} />
 )}

首先输入(从componentDidMount开始加载的图像)在输入中键入并按Enter键后将被替换,但是如果您键入其他内容并按Enter键,则会将新的搜索结果添加到末尾。相反,我想替换以前的搜索结果。我一直在努力找出如何实现这一目标。我尝试添加newSearch状态并在searchImages: []中设置searchStart: 1handleSubmit,但是两者都没有任何区别。作为一个React新手,我还尝试在无限滚动组件中渲染图像后将newSearch设置为false,由于无限循环而中断了应用程序。

任何帮助将不胜感激。

父母:

export class Images extends Component {
  state = {
    images: [],
    searchImages: [],
    count: 30,
    start: 1,
    searchStart: 1,
    term: '',
    search: false,
    newSearch: false
  };

  componentDidMount() {
    const { count, start } = this.state;
      axios
        .get(`/api/photos?count=${count}&start=${start}`)
        .then(res => this.setState({ images: res.data }));
  }

  fetchImages = () => {
    const { count, start, images } = this.state;
    // Will be at 1, then 31 (1 + 30), then 61 (31 + 30), and so forth
    this.setState({ start: start + count });
    axios
      .get(`/api/photos?count=${count}&start=${start}`)
      .then(res =>
        this.setState({ images: images.concat(res.data) })
      );
  }

  fetchSearchImages = () => {
    const { searchStart, count, term, searchImages } = this.state;
    this.setState({
      searchStart: searchStart + count
    });
    axios
      .get(`/api/photos/search?term=${term}&count=${count}&start=${searchStart}`)
      .then(res =>
        this.setState({
          searchImages: searchImages.concat(res.data.results)
        })
      );
  }

  handleSubmit = () => {
    this.setState({
      searchImages: [],
      searchStart: 1,
      search: true,
      newSearch: true
    });

    this.fetchSearchImages();
  }

  handleInputChange = (e) => {
    this.setState({
      term: e
    });
  }

  render() {
    return (
      <>

      <SearchInput onSearch={this.handleInputChange} onFormSubmit={this.handleSubmit} term={this.state.term} />

      <div className="images">
        <InfiniteScroll
          dataLength={this.state.newSearch || this.state.search ? this.state.searchImages.length : this.state.images.length}
          next={this.state.search ? this.fetchSearchImages : this.fetchImages}
          hasMore={true}
          loader={
            <div className="loader-dots">
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
            </div>
          }
        >
        {this.state.newSearch || this.state.search ? this.state.searchImages.map(image =>
          <Image key={image.id} image={image} />
        ) : this.state.images.map(image =>
          <Image key={image.id} image={image} />
        )}
      </InfiniteScroll>
      </div>

      </>
    );
  }
}

子搜索组件:

const SearchInput = props => {

  const onSubmit = e => {
    // Prevents GET request/page refresh on submit
    e.preventDefault();
    props.onFormSubmit();
  };

  return (
    <form onSubmit={onSubmit}>
      <div className="control">
        <input autoFocus value={props.term} onChange={e => props.onSearch(e.target.value)} className="input" type="text" placeholder="Search" />
      </div>
    </form>
  );
}
javascript reactjs infinite-scroll
2个回答
1
投票

fetchSearchImages中的当前代码在React真正设置状态之前依赖状态。我已经通过使用fetchSearchImages的回调参数将PR发送到您的存储库以仅在设置状态后调用setState

基本上是此代码

handleSubmit = () => {
  this.setState({
    searchImages: [],
    searchStart: 1,
    search: true,
    newSearch: true
  });

  this.fetchSearchImages();
}

需要更改为此:

handleSubmit = () => {
  this.setState({
    searchImages: [],
    searchStart: 1,
    search: true,
    newSearch: true
  }, this.fetchSearchImages);
}

0
投票

除了这部分,我认为您的逻辑没有任何问题:

© www.soinside.com 2019 - 2024. All rights reserved.