I use react-apollo useLazyQuery hook. My goal to use it in fetch more button click. However, when I try to use it the fetchMore function is undefined.
Here the call to it:
const [getMyData,{ loading, data, fetchMore }] = useLazyQuery(
myQuery,
{
notifyOnNetworkStatusChange: true,
fetchPolicy: 'network-only',
variables: {}
})
Even if I run lazy on component ready, fetchMoreStill undefined. The question is why it is undefined?
"apollo-client": "^2.6.4", "react-apollo": "^3.1.3",
Did you call the getMyData at the first time?
fetchMore is a function only after the first fetch (with the main the lazyQuery function)
@hadasmaimon yes I did
Even if I run lazy on component ready, fetchMore still undefined
I was able to solve mine by checking if fetchMore is undefined like:
if (fetchMore === undefined) return;
fetchMore({});
Any progress?
Same issue.
Guys this is driving me crazy. I have absolutely no workaround for this issue. No matter what I do, the fetchMore function is said to be undefined even though it clearly is and it passes all the nullish coalescence tests. Debugging and console logging shows that it clearly is an object in good shape and form and yet I'm getting:
TypeError: Cannot read property 'fetchMore' of undefined
at QueryData._this.obsFetchMore (QueryData.ts:493)
at handleFetchMore (List.tsx:123)
at List.tsx:159
at invokePassiveEffectCreate (react-dom.development.js:23487)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
at invokeGuardedCallback (react-dom.development.js:4056)
at flushPassiveEffectsImpl (react-dom.development.js:23574)
at unstable_runWithPriority (scheduler.development.js:646)
at runWithPriority$1 (react-dom.development.js:11276)
at flushPassiveEffects (react-dom.development.js:23447)
at performSyncWorkOnRoot (react-dom.development.js:22269)
at react-dom.development.js:11327
at unstable_runWithPriority (scheduler.development.js:646)
at runWithPriority$1 (react-dom.development.js:11276)
at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
at flushSyncCallbackQueue (react-dom.development.js:11309)
at discreteUpdates$1 (react-dom.development.js:22420)
at discreteUpdates (react-dom.development.js:3756)
at dispatchDiscreteEvent (react-dom.development.js:5889) "
at List (https://localhost:3000/static/js/18.chunk.js:3028:77)
at InnerLoadable (https://localhost:3000/static/js/15.chunk.js:313374:34)
at Route (https://localhost:3000/static/js/15.chunk.js:488990:29)
at Switch (https://localhost:3000/static/js/15.chunk.js:489192:29)
at PodcastsRouter (https://localhost:3000/static/js/57.chunk.js:65:3)
at Podcasts (https://localhost:3000/static/js/57.chunk.js:249:3)
at InnerLoadable (https://localhost:3000/static/js/15.chunk.js:313374:34)
at Route (https://localhost:3000/static/js/15.chunk.js:488990:29)
at Switch (https://localhost:3000/static/js/15.chunk.js:489192:29)
at MainRouter (https://localhost:3000/static/js/main.chunk.js:10612:3)
at div
at Transition (https://localhost:3000/static/js/15.chunk.js:494285:30)
at CSSTransition (https://localhost:3000/static/js/15.chunk.js:493402:35)
at SwitchTransition (https://localhost:3000/static/js/15.chunk.js:494036:35)
at main
at div
at Main (https://localhost:3000/static/js/main.chunk.js:10888:88)
at Route (https://localhost:3000/static/js/15.chunk.js:488990:29)
at Switch (https://localhost:3000/static/js/15.chunk.js:489192:29)
at AppRouter
at App (https://localhost:3000/static/js/main.chunk.js:1700:78)
at Router (https://localhost:3000/static/js/15.chunk.js:488625:30)
at BrowserRouter (https://localhost:3000/static/js/15.chunk.js:487290:35)
at ApolloProvider (https://localhost:3000/static/js/15.chunk.js:49896:19)"
Any help (even a dirty hack) would be highly appreciated.
@apollo/client 3.2.5
react 17.0.1
Here my workaround:
E.g you have parent component add in it state:
[data, setData] = useState({})
Call YouQueryRunComponent data={data} setData={setData}/
In component add next:
const [getData, { data:dataResult }] = useLazyQuery(
getMyData,
{
fetchPolicy: 'cache-and-network',
variables: {},
}
);
useEffect(() => {
isEmptyObject(data) && getData();
}, []);
useEffect(() => {
//Here DataResult will arrive
getDataResult && setData(getDataResult)
}, [getDataResult]);
return <ComponentRender...>
Then fethmore will be avaiable
Lovely, @sashberd .
My workaround was to refactor all useLazyQuery-related code into a custom React hook. For some reason, doing all the fetchMore work and new calls in a separate hook works whereas doing it within the same component doesn't. May be an interesting avenue to explore.
@sashberd and @antikvarBE suggestions are good and what I finally settled for.
Dropping this here to save someone some troubles (Future ME 馃槃 ).
fetch-more-hook.ts.
import { DocumentNode, OperationVariables, QueryHookOptions, useQuery } from "@apollo/client";
export function useFetchMore<TData = any, TVariables = OperationVariables>(Query: DocumentNode, options: QueryHookOptions<TData, TVariables> = {}){
const { loading, error, data, fetchMore, ...others } = useQuery<TData, TVariables>(Query, options);
return { loading, error, data, fetchMore, ...others };
}
Yousage:
const { loading, error, data, fetchMore } = useFetchMore<{items: Item[], fetchMore:any}>(YOUR_GQL_QUERY);
Then calling it like:
const onLoadMore = useCallback(() => {
fetchMore({
variables: {
_id: data?.items[data?.items.length - 1]?._id
}
});
}, [data?.items, fetchMore]);
Glad common wisdom is being shared here for other struggling peeps.
I noticed another weirdness with useLazyQuery recently (which is probably related):
My custom React hook solution would work the first time but if I call my hook for the second time immediately after the first call, it'll still have that fetch more undefined issue.
I ended up completely giving up on useLazyQuery in favor of using useQuery with skip: true. This feels like a hack but makes my code work exactly the way useLazyQuery promised it would.
Use skip:true and your fetchMore will be doing what you want it to do.
Leaving comment with my solution, hopefully this helps someone.
In my case, the error happened because I mistakenly called the function to get initial data more than once. This seems to have caused the internal Apollo state to break and in turn caused an error when calling fetchMore