TypeError: Cannot read property 'fetchMore' of undefined in Apollo

Viewed 961

I'm implementing an infinite scroll with Apollo and React. Everything works fine. When I navigate away from Feed and then back to Feed I'm getting this weird error:

TypeError: Cannot read property 'fetchMore' of undefined

Has anyone else had experience with this issue? I found this but there doesn't seem to yet be any solutions. One of the answers mentions a partial solution "checking the route before executing fetchMore" but I don't know what means.

I'm still in the middle of development so I haven't had a chance to clean this component up yet, but here it is:

import React, { useEffect, useRef } from 'react';
import { useQuery } from '@apollo/client';
import PostUpdateOrShow from '../posts/types/showOrUpdate/PostUpdateOrShow.js'
import Cookies from 'js-cookie';
import Queries from '../../graphql/queries';
import InfiniteScroll from './util/Infinite_Scroll.js';
const { FETCH_USER_FEED, FETCH_TAG_FEED } = Queries;

const Feed = ({
  user, tag
}) => {
  let fetchMoreDiv = useRef(null);
  let cursorId = useRef(null);
  
  useEffect(() => {
    var scroll = document.addEventListener('scroll', function(event) {
      fetchMoreDiv.current = document.querySelector('#fetchMore')
      var el = fetchMoreDiv.current.getBoundingClientRect()
      var elTop = el.top
      var elBottom = el.bottom
      var innerHeight = window.innerHeight
      
      if (elTop >= 0 && elBottom <= innerHeight) {
        fetchMore({
          query: gqlQuery,
          variables: {
            query: query,
            cursorId: cursorId.current
          },
        })
      }
    })

    return () => {
      document.removeEventListener('scroll', scroll)
    }
  })

  var gqlQuery
  var query
  if (user) {
   gqlQuery = FETCH_USER_FEED
   query = user.blogName
  } else if (tag) {
   gqlQuery = FETCH_TAG_FEED
   query = tag.title.slice(1)
  } else {
   gqlQuery = FETCH_USER_FEED
   query = Cookies.get('currentUser')
  }
  
  let { loading, error, data, fetchMore } = useQuery(gqlQuery, {
    variables: {
      query: query,
      cursorId: null
    },
  })
  
  if (loading) return 'Loading...';
  if (error) return `Error: ${error}`;
  
  const { fetchUserFeed, fetchTagFeed } = data

  cursorId.current = fetchUserFeed ? fetchUserFeed[fetchUserFeed.length - 1]._id :
  fetchTagFeed[fetchTagFeed.length - 1]._id
  
  if (tag) {
    return(
      <div>
        <div>
          {fetchTagFeed.map((post, i) => {
            return (
              <div
                className='post'
                key={post._id}
              >
                <PostUpdateOrShow
                  post={post}
                />
              </div>
            )
          })}
          </div>
          <InfiniteScroll 
            fetchMoreDiv={fetchMoreDiv}
          />
          <div
            id='fetchMore'
          >
          </div>
      </div>
    )
  } else {
    return(
      <div>
        <div>
          {fetchUserFeed.map((post, i) => {
            return (
              <div
                className='post'
                key={post._id}
              >
                <PostUpdateOrShow
                  post={post}
                />
              </div>
            )
          })}
          </div>
          <InfiniteScroll 
            fetchMoreDiv={fetchMoreDiv}
          />
          <div
            id='fetchMore'
          >
          </div>
      </div>
    )
  }
}

export default Feed;

Apollo client config:

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
       fields: {
         fetchLikesRepostsAndComments: {
           merge: (existing = [], incoming = []) => {
             return incoming
           }
        },
        fetchUserFeed: {
          keyArgs: ['query'],
            merge: (existing = [], incoming = []) => {
            const elements = [...existing, ...incoming].reduce((array, current) => {
              return array.map(i => i.__ref).includes(current.__ref) ? array : [...array, current];
            }, []);
            
            return elements
        },
        }
      }
    }
  }
  }),
  errorLink
})
1 Answers

I believe the issue is that you are using fetchMore within useEffect hook. Try to rethink your code to avoid this. Using fetchMore outside the hook would work flawlessly.

Related