Imagine a Cascader component, which has two Select components, in which the second one depends on the selected item from the first component.
In this case, could useSWR supports lazy fetcher by returning a refetch function which can be run later ?
const { data, error, refetch } = useSWR(key, { lazy: true })
You can use mutate in that case right?
const { data } = useSWR('select-data')
return <>
{data}
<button onClick={() => {
mutate('select-data', fetch('/api'))
}}>lazy fetch</button>
</>
In fact, mutate is so flexible that can be used in both prefetching and lazy fetching.
Feel free to reopen if you have other questions! 馃檹
I agree that a lazy option would be nice, but for now, here is my solution for a useLazyRequest hook:
const request = async () => {
// whatever your request function is
};
type LazyRequestTuple<R, V extends Variables = Variables> = [
(v: V) => Promise<void>,
ResponseInterface<R | null, Error>
];
export const useLazyRequest = <R, V extends Variables = Variables>(
query: DocumentNode
): LazyRequestTuple<R, V> => {
const response = useSWR<R | null>(print(query), () => {
return null;
});
const executeQuery = async (variables?: V) => {
const result = await request<R>(query, variables);
response.mutate(result, false);
};
return [executeQuery, response];
};
I am using Swr to check user login, It run on top request, and you know run deserializeUser will take much time.
Hmm how can just run auth check when windowload.
@good-idea Sorry, I am just new here, so hard to read your code.
@warcraft14115 Here is a gist that has a more complete example:
https://gist.github.com/good-idea/b36f9715aedee44b1ba44b938dc02224
I haven't tested it out, leave a comment on the gist if you have any problems!
@shuding or any other maintainers: my solution in the gist is working for me for now, but it was surprisingly complicated to get it to work. Compared to the example in my comment, the gist solution includes the variables (stringified) within the query key (Passing it in as a plain object caused infinite rerenders).
But, it's still not ideal as you now need to know what your variables are going to be before you call useLazyRequest. There are ways to get around it but it would require changing the architecture of your component, but it's not ideal.
Setting up this whole hook is a decent amount of boilerplate that will need to be copied from the gist into each project. That's fine for me, for now.
But, I'd say that lazy requests are common enough of a scenario to consider adding 1st-class support for it in the API - preferably, one that allows you to call refetch with different variables, since the user might not always have those handy at the time of initialization.
Most helpful comment
@shuding or any other maintainers: my solution in the gist is working for me for now, but it was surprisingly complicated to get it to work. Compared to the example in my comment, the gist solution includes the variables (stringified) within the query key (Passing it in as a plain object caused infinite rerenders).
But, it's still not ideal as you now need to know what your variables are going to be before you call
useLazyRequest. There are ways to get around it but it would require changing the architecture of your component, but it's not ideal.Setting up this whole hook is a decent amount of boilerplate that will need to be copied from the gist into each project. That's fine for me, for now.
But, I'd say that lazy requests are common enough of a scenario to consider adding 1st-class support for it in the API - preferably, one that allows you to call
refetchwith different variables, since the user might not always have those handy at the time of initialization.