Рефакторинг от обещания к asyn c ждут и используют нумерацию страниц - PullRequest
0 голосов
/ 20 апреля 2020

Я пытаюсь повторно использовать этот код для использования async/await

fetchTopRatedMovies(pageNumber).then((newData) =>
      setApiData({
        ...newData,
        results: [...apiData.results, ...newData.results]
      })
    );

Я пытаюсь использовать его в блоке try catch внутри useEffect

Вот что Я до сих пор.

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `${baseURL}${option}?api_key=${API_KEY}&language=en&page=${pageNumber}&region=GB`
        );
        const data = await response.json();
        setMovieData({
          ...movieData,
          ...data,
        });
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    };
    setLoading(true);
    fetchData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [option, pageNumber]);

Проблема в том, я думаю, является ли эта часть

 const data = await response.json();
        setMovieData({
          ...movieData,
          ...data,
        });

Поскольку мое состояние const [movieData, setMovieData] = useState({ page: 0, results: [] }); не обновляется со старыми данными только новые данные, которые изменяются на pageNumber увеличение.

Моя главная цель - иметь кнопку, которая добавляет больше данных к уже отображаемым данным.

Полный код на данный момент:


export const Directory = () => {
  const [option, setOption] = useState('popular');
  const [pageNumber, setPageNumber] = useState(1);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);
  const [movieData, setMovieData] = useState({ page: 0, results: [] });

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `${baseURL}${option}?api_key=${API_KEY}&language=en&page=${pageNumber}&region=GB`
        );
        const data = await response.json();
        setMovieData({
          ...movieData,
          ...data,
        });
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    };
    setLoading(true);
    fetchData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [option, pageNumber]);

  const { results, page, total_pages } = movieData;

  const handleOptionChange = e => {
    setOption(e.target.value);
    setPageNumber(1);
  };
  const pageLimit = page === 0 || page < total_pages;

  return (
    <div>
      <select value={option} onChange={e => handleOptionChange(e)}>
        <option value='popular'>Popular</option>
        <option value='top_rated'>Top Rated</option>
        <option value='now_playing'>Now Playing</option>
      </select>
      <ul>
        {results &&
          results.map(movie => {
            return <li key={movie.id}>{movie.title}</li>;
          })}
      </ul>
      {results && (
        <button
          disabled={!pageLimit}
          onClick={() => setPageNumber(pageNumber + 1)}>
          More
        </button>
      )}
    </div>
  );
};

Только в настоящее время данные результатов на одной странице отображаются одновременно. Так что для первого рендера страницы 1. Затем, когда я нажимаю кнопку больше. Получает результаты на странице 2. Однако он отображает только одну страницу за раз. Я хочу, чтобы новые результаты были добавлены к уже обработанным данным. Таким образом, с каждым нажатием кнопки отображаются дополнительные результаты.

console.log из data = await response.json()

{
  "page": 1,
  "total_results": 10000,
  "total_pages": 500,
  "results": [
    {
      "popularity": 728.376,
      "vote_count": 3070,
      "video": false,
      "poster_path": "/xBHvZcjRiWyobQ9kxBhO6B2dtRI.jpg",
      "id": 419704,
      "adult": false,
      "backdrop_path": "/5BwqwxMEjeFtdknRV792Svo0K1v.jpg",
      "original_language": "en",
      "original_title": "Ad Astra",
      "genre_ids": [
        18,
        878
      ],
      "title": "Ad Astra",
      "vote_average": 6,
      "overview": "The near future, a time when both hope and hardships drive humanity to look to the stars and beyond. While a mysterious phenomenon menaces to destroy life on planet Earth, astronaut Roy McBride undertakes a mission across the immensity of space and its many perils to uncover the truth about a lost expedition that decades before boldly faced emptiness and silence in search of the unknown.",
      "release_date": "2019-09-18"
    },
    {
      "popularity": 220.799,
      "id": 454626,
      "video": false,
      "vote_count": 2868,
      "vote_average": 7.5,
      "title": "Sonic the Hedgehog",
      "release_date": "2020-02-14",
      "original_language": "en",
      "original_title": "Sonic the Hedgehog",
      "genre_ids": [
        28,
        878,
        35,
        10751
      ],
      "backdrop_path": "/stmYfCUGd8Iy6kAMBr6AmWqx8Bq.jpg",
      "adult": false,
      "overview": "Based on the global blockbuster videogame franchise from Sega, Sonic the Hedgehog tells the story of the world’s speediest hedgehog as he embraces his new home on Earth. In this live-action adventure comedy, Sonic and his new best friend team up to defend the planet from the evil genius Dr. Robotnik and his plans for world domination.",
      "poster_path": "/aQvJ5WPzZgYVDrxLX4R6cLJCEaQ.jpg"
    },
    {
      "popularity": 204.235,
      "vote_count": 3202,
      "video": false,
      "poster_path": "/y95lQLnuNKdPAzw9F9Ab8kJ80c3.jpg",
      "id": 38700,
      "adult": false,
      "backdrop_path": "/upUy2QhMZEmtypPW3PdieKLAHxh.jpg",
      "original_language": "en",
      "original_title": "Bad Boys for Life",
      "genre_ids": [
        28,
        80,
        53
      ],
      "title": "Bad Boys for Life",
      "vote_average": 7.2,
      "overview": "Marcus and Mike are forced to confront new threats, career changes, and midlife crises as they join the newly created elite team AMMO of the Miami police department to take down the ruthless Armando Armas, the vicious leader of a Miami drug cartel.",
      "release_date": "2020-01-17"
    }
  ]
}

1 Ответ

0 голосов
/ 20 апреля 2020

Ваша структура movieData:

{ page: 0, results: [] }

Когда вы делаете:

setMovieData({
  ...movieData,
  ...data,
})

Она просто заменяет предыдущие данные новыми. Потому что ключи как новых, так и старых данных совпадают. Вам нужно сделать что-то вроде этого:

setMovieData({
  results: [
      ...movieData.results, ...data.results
  ],
  page: data.page
})

Это добавит новые данные после старых. Надеюсь, это поможет.

Другая ошибка связана со следующим кодом:

const pageLimit = page === 0 || page < total_pages;

Это необходимо сделать напрямую с состоянием movieData. Обновите ваш код следующим образом:

  return (
    <div>
      <select value={option} onChange={e => handleOptionChange(e)}>
        <option value='popular'>Popular</option>
        <option value='top_rated'>Top Rated</option>
        <option value='now_playing'>Now Playing</option>
      </select>
      <ul>
        {movieData.results &&
          movieData.results.map(movie => {
            return <li key={movie.id}>{movie.title}</li>;
          })}
      </ul>
      {movieData.results && (
        <button
          disabled={!(movieData.page === 0 || movieData.page < total_pages)}
          onClick={() => setPageNumber(pageNumber + 1)}>
          More
        </button>
      )}
    </div>
  );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...