-
-
Notifications
You must be signed in to change notification settings - Fork 451
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
(fix) - fetching on initial render #248
Changes from 4 commits
1efab44
79ac12d
ac7a89d
4d03ae5
ae149ef
0175321
1c435d3
00b0869
b030115
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,19 +33,33 @@ export type UseQueryResponse<T> = [ | |
export const useQuery = <T = any, V = object>( | ||
args: UseQueryArgs<V> | ||
): UseQueryResponse<T> => { | ||
const isMounted = useRef(false); | ||
const unsubscribe = useRef(noop); | ||
const initialState = useRef({ fetching: true }); | ||
const updateState = useRef(update => { | ||
initialState.current = update; | ||
}); | ||
|
||
const client = useContext(Context); | ||
|
||
const request = useMemo( | ||
() => createRequest(args.query, args.variables as any), | ||
[args.query, args.variables] | ||
); | ||
|
||
const [state, setState] = useState<UseQueryState<T>>({ | ||
fetching: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we simplify this PR to only change the initial state? This line being changed from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I suppose this PR is still in a more "experimental" stage so maybe we can merge yours for now and if that leads to conflicts I can later resolve them 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Adding this logic to executeQuery would not solve the problem of the initial rendering state though? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Talking about pause this should probably also be accounted in first render trying to get from cache else we’d make that option obsolete for first call. |
||
error: undefined, | ||
data: undefined, | ||
}); | ||
if (!isMounted.current) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like the idea of reusing I suppose we could also reuse Maybe it could check whether I'm also not sure how This would at least simplify the implementation since in summary we can:
Edit: Btw thanks again for picking this up! Means a lot since this is one of the more important changes and it's always great to have more people helping out 🙏 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see how we can reuse executeQuery since to use that we already need our setState defined, that useState inturns relies on initialState.current. I did implement the second remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, true, reusing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added a few suggestions but if I'm not mistaken, the issue described leaves us only concerned about the initial state on mount. It looks like we have two scenarios:
If that's the case, we can make this change without the need for refs or additional logic. const [state, setState] = useState<UseQueryState<T>>({
fetching: args.pause !== true,
error: undefined,
data: undefined,
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other scenario is some preparation for suspense SSR so we'll also would want to keep the executeQuery excursion that runs on initial mount outside of useEffect But depending on how React works the executeQuery useCallback could maybe be reused for that, simplifying this PR. We'll see how that pans out I guess. Might or might nor work 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm out of here 👀 Are you saying that following SSR, the state and ref values are not synchronized from the backend? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Up to you what this PR becomes, my initial solution was to make the initial state based on pause. If the current wip helps out more for future work maybe we can make a seperate simple solution PR and keep this one for the experimental work. |
||
const [teardown] = pipe( | ||
client.executeQuery(request, { | ||
requestPolicy: args.requestPolicy, | ||
}), | ||
subscribe(({ data, error }) => { | ||
updateState.current({ data, error, isFetching: false }); | ||
}) | ||
); | ||
unsubscribe.current = teardown; | ||
} | ||
|
||
const [state, setState] = useState<UseQueryState<T>>(initialState.current); | ||
|
||
const executeQuery = useCallback( | ||
(opts?: Partial<OperationContext>) => { | ||
|
@@ -76,7 +90,16 @@ export const useQuery = <T = any, V = object>( | |
); | ||
|
||
useEffect(() => { | ||
executeQuery(); | ||
isMounted.current = true; | ||
JoviDeCroock marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return () => { | ||
isMounted.current = false; | ||
}; | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (isMounted.current) { | ||
executeQuery(); | ||
} | ||
return unsubscribe.current; | ||
JoviDeCroock marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, [executeQuery]); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoviDeCroock heads up, this is going to conflict with an existing pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jup, saw that but in theory that invokes a will mount, no?