Как один раз вызвать api и удалить прослушиватель событий, как только вы дойдете до нижней части страницы?

#javascript #reactjs

Вопрос:

Я реализовал бесконечную прокрутку, чтобы получать больше данных всякий раз, когда пользователь достигает нижней части страницы. Кажется, это работает нормально, но у меня особое состояние.

Когда страница отображается в первый раз, я получаю ответ в виде :

 count: 47
next: "http://localhost:8000/api/user/groups/56/users/?limit=20amp;offset=20"
previous: null
results: [{id: "79", email: "priyanka LarryLo@emembler.com", first_name: "Larry", last_name: "Lo",…},…]
 

Где count представляет общее количество элементов в массиве, в строке «далее» ограничение установлено равным 20, что означает, что я получаю максимум 20 элементов для каждого вызова api, и offest показывает, что для получения следующих элементов я должен дать смещение «20» при следующем вызове api.
Как только все данные будут извлечены, значение «next» будет равно нулю, поэтому я поставил условие примерно так: если значение «next» равно нулю, не вызывайте api, но вызов api будет дан.

Код редуктора для хранения извлекаемых данных:

 case GET_MEMBERS_OF_GROUP: {
  newState["nextMembers"] =action.payload.response.next;
  if (action.payload.response.results) {
    let newArray = newState["members"].concat(
      action.payload.response.results
    );
    newState["members"] = newArray;
  } else {
    newState["members"] = action.payload.response.results;
  }
  if(action.payload.page == 0){
    newState["members"] = action.payload.response.results
  }  
  return newState;
}
 

У меня есть еще один редуктор для обновления смещения, которое будет предоставлено при следующем вызове api:

    case SHOW_NEXT_MEMBERS: {
      newState["pageOfmembers"] = newState["pageOfmembers"]   action.payload.nextMembers;
      return newState;
    }
 

Реализация бесконечной прокрутки, где смещение не увеличивается, а также когда значение «следующий» равно нулю, вызывается api:

  const [nextmembers, setNextmembers] = useState()

  useEffect(() => {
    setNextmembers(data.nextMembers)
  },[data.nextMembers])

  useEffect(() => {
    const event = window.addEventListener('scroll', () => {
      if ((window.innerHeight   window.scrollY) == document.body.scrollHeight ) {
        if(nextmembersamp;amp; window.location.href.includes("/members")){

          dispatch({
            type: SHOW_NEXT_MEMBERS,
            payload: {
              nextMembers:  20,
            },
          })
          setTimeout(() => {
            dispatch(EMDoGetMembersOfGroupAction({id:data.singleGroup.id ? data.singleGroup.id : window.sessionStorage.getItem("GroupId"), limit:data.pageOfmembers}))
          },500)
        } 
      }
    })
    return () => window.removeEventListener('scroll', event);
  }, [nextmembers])
 

Комментарии:

1. addEventListener возвращает неопределенное значение ( developer.mozilla.org/en-US/docs/Web/API/EventTarget/… ). Таким образом, переменная события должна быть неопределенной, и removeEventListener ничего не делает. Вам нужно будет сохранить функцию обработки событий в переменной, а затем использовать эту переменную в addEventListener и removeEventListener.

2. Не могли бы вы привести мне один пример с моим существующим кодом?

Ответ №1:

Так что это может быть не все решение, но часть проблемы заключается в том, как вы используете addEventListener и removeEventListener. Вам нужно сохранить функцию обработки событий в переменной, а затем использовать эту переменную с помощью addEventListener и removeEventListener.

 
const [nextmembers, setNextmembers] = useState()

useEffect(() => {
  setNextmembers(data.nextMembers)
},[data.nextMembers])


const handleScroll = useCallback(() => {
        // all the logic in that anonymous function goes here
    if ((window.innerHeight   window.scrollY) == document.body.scrollHeight ){
        // ...  
    }
}, [!!nextMembers])

useEffect(() => {
  window.addEventListener('scroll', handleScroll)
  return () => window.removeEventListener('scroll', handleScroll)
}, [handleScroll])