API-интерфейс Intersection Observer вызывает обратный вызов для старой цели наблюдения - PullRequest
0 голосов
/ 30 июня 2019

Фон

Я работаю над простым приложением песни, встроенным в React.

Цель

Использование Intersection ObserverAPI для загрузки большего количества исполнителей, когда пользователь прокручивает список исполнителей вниз.

Информация

API, управляющий внешним интерфейсом, имеет подкачку страниц.offset начинается с 0, а limit - 10.Вызов API выглядит следующим образом:

https://api.bejebeje.com/artists?offset=0&limit=10

Все приложение развернуто здесь .У меня есть полезные операторы console.log() в коде, поэтому поможет открытие Chrome Dev Tools.

Код

Весь код с открытым исходным кодом и сидит наGitHub .Ветвь, над которой я работаю: feature / intersection-api-extensions .

Вот компонент App.jsx:

import React, { useRef, useCallback, useState, useEffect } from "react";
import { render } from "react-dom";
import { Router } from "@reach/router";
import axios from "axios";
import Authorisation from "./components/Authorisation/Authorisation";
import Artists from "./components/Artists/Artists";
import ArtistLyrics from "./components/ArtistLyrics/ArtistLyrics";
import Lyric from "./components/Lyric/Lyric";
import { API_CONSTANTS } from "./helpers/apiEndpoints";
import "./App.css";

function App() {
  const [artists, setArtists] = useState([]);
  const offset = useRef(0);
  const limit = 10;

  const callback = entries => {
    console.log(
      `Intersection callback fired. isIntersecting is ${
        entries[0].isIntersecting
      }.`
    );
    if (entries[0].isIntersecting) {
      console.log("about to fetch artists ...");
      fetchArtists(offset, limit);
    }
  };

  const fetchArtists = (offset, limit) => {
    axios.get(API_CONSTANTS.artists(offset.current, limit)).then(result => {
      const artistsArray = result.data.artists;
      setArtists([...artists, ...artistsArray]);
      offset.current += artistsArray.length;
      console.log(`offset is now at ${offset.current}.`);
    });
  };

  useEffect(() => {
    fetchArtists(offset, limit);
  }, []);

  return (
    <div>
      <Router>
        <Artists path="/" artists={artists} intersectionCallback={callback} />
        <ArtistLyrics path="artists/:artistSlug/lyrics" />
        <Lyric path="artists/:artistSlug/lyrics/:lyricSlug" />
        <Authorisation path="/callback" />
      </Router>
    </div>
  );
}

render(<App />, document.getElementById("root"));

А вот Artists.jsx компонент:

import React, { useEffect, useRef } from "react";
import Header from "../Header/Header";
import "./Artists.css";
import ArtistCard from "../ArtistCard/ArtistCard";

function Artists(props) {
  const getPrimaryArtistSlug = slugs => {
    return slugs.filter(slug => slug.isPrimary)[0].name;
  };

  const singleRefs = props.artists.reduce((acc, value, index) => {
    acc[index] = React.createRef();
    return acc;
  }, {});

  const observer = new IntersectionObserver(props.intersectionCallback, {
    root: null,
    threshold: 0.8
  });

  useEffect(() => {
    if (props.artists.length > 0) {
      const indexOfLastArtist = props.artists.length - 2;
      observer.observe(singleRefs[indexOfLastArtist].current);
      const entries = observer.takeRecords();
    }
  }, [props.artists]);

  return (
    <>
      <Header title="Browse" />
      <div className="artists__list">
        {props.artists.map((artist, index) => {
          const primarySlug = getPrimaryArtistSlug(artist.slugs);
          return (
            <ArtistCard
              key={primarySlug}
              artist={artist}
              primarySlug={primarySlug}
              itemRef={singleRefs[index]}
            />
          );
        })}
      </div>
    </>
  );
}

export default Artists;

Проблема

При каждом повторном рендеринге Artists.jsx я получаю новый IntersectionObserver и затем устанавливаю наблюдениецелевой элемент до последнего в массиве художников.Поэтому, когда у props.artists есть 10 элементов, цель - 9-й художник в списке.Когда props.artists имеет 20 элементов, целью является 19-й исполнитель в списке и т. Д.

При начальной загрузке страницы все работает, как и ожидалось, я прокручиваю вниз до 9-го элемента и получаю новыйвыполняется вызов API, и загружаются и обрабатываются еще 10 художников.

Новая цель должна быть 19-м художником.И все же, если я прокручиваю вверх, затем прокручиваю вниз мимо 9-го художника, обратный вызов снова срабатывает!Это почему?Девятый элемент артиста больше не является целью наблюдателя, поэтому я не уверен, почему он вызывает обратный вызов, когда он появляется.Я в замешательстве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...