Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot read property 'fetchMore' of undefined #8071

Open
johnobrien8642 opened this issue Apr 28, 2021 · 5 comments
Open

TypeError: Cannot read property 'fetchMore' of undefined #8071

johnobrien8642 opened this issue Apr 28, 2021 · 5 comments
Labels
🔍 investigate Investigate further

Comments

@johnobrien8642
Copy link

johnobrien8642 commented Apr 28, 2021

Intended outcome:

When using infinite scroll cursor based pagination user should should be able to navigate away from the feed and then back to the feed and have fetchMore continue to work.

Here's an example of a Feed component:

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 } = Queries;

const CurrentUserFeed = ({
  user, tag
}) => {
  let fetchMoreDiv = useRef(null);
  let cursorId = useRef(null);

  useEffect(() => {

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

  
  let { loading, error, data, fetchMore } = useQuery(FETCH_USER_FEED, {
    variables: {
      query: Cookies.get('currentUser'),
      cursorId: null
    },
  })

  var scroll = window.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: FETCH_USER_FEED,
        variables: {
          query: Cookies.get('currentUser'),
          cursorId: cursorId.current
        },
      })
    }
  })
  
  if (loading) return 'Loading...';
  if (error) return `Error: ${error}`;
  
  const { fetchUserFeed } = data

  cursorId.current = fetchUserFeed[fetchUserFeed.length - 1]._id

  return(
    <div>
      <div>
        {fetchUserFeed.map((post, i) => {
          return (
            <div
              className='post'
              key={post._id}
            >
              <PostUpdateOrShow
                post={post}
              />
            </div>
          )
        })}
        </div>
  
        <div
          id='fetchMore'
        >
        </div>
    </div>
  )
}

export default CurrentUserFeed;

Actual outcome:

This error occurs and breaks the application:
Screen Shot 2021-04-28 at 10 37 36 AM

How to reproduce the issue:

This is my field policy:

fetchUserFeed: {
          keyArgs: ['query'],
            merge: (existing = [], incoming = []) => {
              console.log(incoming)
            const elements = [...existing, ...incoming].reduce((array, current) => {
              return array.map(i => i.__ref).includes(current.__ref) ? array : [...array, current];
            }, []);
            
            return elements
          },
        },

If I console log incoming I can see the returned results, but error still occurs.

I've decided I'm going to try to use useApolloClient to circumvent fetchMore entirely. Would be awesome to find out I'm doing something wrong or it would be awesome to get this bug fixed if it is indeed one. Really appreciate everyones hard work, I really enjoy learning and using Apollo, looking forward to resolving this.

I've seen one or two similar issues but I believe my situation is different enough to warrant a new issue.

Versions

System:
OS: macOS 11.2.3
Binaries:
Node: 15.11.0 - ~/.nvm/versions/node/v15.11.0/bin/node
npm: 7.6.0 - ~/.nvm/versions/node/v15.11.0/bin/npm
Browsers:
Chrome: 90.0.4430.93
Safari: 14.0.3

Apollo and React version:

"@apollo/client": "^3.3.15",
"react": "^17.0.1",

@benjamn
Copy link
Member

benjamn commented Apr 30, 2021

@johnobrien8642 Is there any chance the React component has unmounted by the time it calls fetchMore? That might explain queryData.currentObservable being undefined (not my final answer, just hoping to diagnose the problem).

@johnobrien8642
Copy link
Author

Hi @benjamn, thanks for the quick response.

I think that this is possible given my understanding of React. The Feed component is a standalone component but as of this error I had written two different parent HOC's that contain Feed and pass different props based on the Route.

For a simple example:

<Switch>
        <AuthRoute path={'/dashboard'} component={Dashboard} />
        <AuthRoute path={'/view/tag/:tagTitle'} component={TagFeed} />
        more routes....
</Switch>

Dashboard and TagFeed both contain the Feed component. Consider this flow: I'm in Dashboard, I go to the search bar and search the tag #nice, it appears as a search result and I click it, navigating to TagFeed, where I see the correct results. I then click the home link, navigating back to Dashboard, and then begin to scroll. When I hit the bottom of the scroll and trigger fetchMore the error is thrown. If I refresh then error clears and fetchMore works.

I'm most confused by why incoming in the fieldPolicy would show any results at all if fetchMore is broken by the component remounting. If the mounting is the issue wouldn't fetchMore be unable to execute at all?

I've got useApolloClient implemented and working on my end so I'm currently past the issue for now. Still interested on figuring this out, I'd like to use fetchMore.

@rebirthtobi
Copy link

rebirthtobi commented May 22, 2021

I am also experiencing this issue, onClick of a search, it returns the result but always getting fetchMore is undefined

 if (fetchMore) {
      fetchMore({
          query:     FETCH_PEOPLE,
          variables: { searchQuery },
      });
  }

Even when I did this to event check, I still get the undefined error

QueryData.ts:494 Uncaught TypeError: Cannot read property 'fetchMore' of undefined
    at QueryData._this.obsFetchMore (QueryData.ts:494)
    at onSearch (index.tsx:59)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070)

@harish-aka-shivi
Copy link

I have faced this issue many times and one thing that seems to be common is this happens after the hot reload of the code. Maybe, I think as the component is refreshed and a new useQuery hook is created, the pending fetchMores might give this exception.

@brainkim brainkim self-assigned this Aug 13, 2021
@hwillson hwillson added the 🔍 investigate Investigate further label May 31, 2022
@gpbaculio
Copy link

Might help anyone, what worked for me is clearing cache, try to restart the emulator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔍 investigate Investigate further
Projects
None yet
Development

No branches or pull requests

7 participants