首页 > 解决方案 > React - useEffect 和分页问题

问题描述

我已经开始用 React 做一些事情,我正在制作一个带有搜索功能的电影应用程序,并在我找到的一些教程的帮助下应用了无限滚动分页。基本上,我的问题是我在网站加载时使用 useEffect() 挂钩来获取电影列表(使用 FEATURED_API),但是我遇到了冲突,因为我使用相同的 useEffect() 进行分页,所以当我搜索电影(使用 SEARCH_API)当我向下滚动时,它也会执行对 FEATURED_API 的调用。有人可以建议我任何可能的解决方案吗?提前致谢。

import React, {useEffect, useState, useRef, useCallback} from 'react';
import Movie from './components/Movie'
import './App.css';

const FEATURED_API = 'https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=(insert some api key here)&page=';
const SEARCH_API = 'https://api.themoviedb.org/3/search/movie?api_key=(insert some api key here)&query=';

function App() {
  const [movies, setMovies] = useState([]);
  const [searchTerm, setSearchTerm] = useState('');
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(false);

  const observer = useRef();
  const lastMovieRef = useCallback(node => {
    if (observer.current) observer.current.disconnect();
    observer.current = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting && hasMore) {
        setPage(prevPage => prevPage + 1);
      }
    })
    if (node) observer.current.observe(node);
  }, [hasMore]);

  useEffect(() => {
    getMovies(FEATURED_API + page);
  }, [page]);

  const getMovies = (API) => {
    fetch(API)
    .then((res) => res.json())
    .then((data) => {
      console.log(data);
      setMovies(prevMovies => {
        return [...new Set([...prevMovies, ...data.results])]
      })
      setHasMore(data.results.length > 0)
    });
  }

  const handleOnSubmit = (e) => {
    e.preventDefault();

    if (searchTerm) {
      setMovies([]);
      setPage(1);
      getMovies(SEARCH_API + searchTerm);
      setSearchTerm('');
    }
  }

  const handleInputChange = (e) => {
    setSearchTerm(e.target.value);
  }

  return (
    <div className="App">
      <header className="header__wrapper">
        <form onSubmit={handleOnSubmit}>
          <input className="search" type="text" value={searchTerm} onChange={handleInputChange} placeholder="Search..." />
        </form>
      </header>
      <section className="movies__wrapper">
        {
          movies.length > 0 &&
          movies.map((movie, index) => {
            if (movies.length === index + 1) {
              return <Movie ref={lastMovieRef} movie={movie} key={movie.id} />
            } else {
              return <Movie movie={movie} key={movie.id} />
            }
          })
        }
      </section>
    </div>
  );
}

export default App;

标签: javascriptreactjsuse-effect

解决方案


这是一个基本的解决方案。您可以设置一个名为 loading 的新状态,并且只有在加载状态为 true 时才能调用 FEATURE_API。调用 API 后,您可以将其设置为 false。所以在分页期间,它不会再被调用。

let [loading, setLoading] = useState(true)
useEffect(() => {
    if(loading === true) {
        getMovies(FEATURED_API + page);
        setLoading(false);
    }
  }, [page]);

推荐阅读