@gqty/react
Version:
The No-GraphQL Client for React
163 lines (158 loc) • 4.46 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const gqty = require('gqty');
const React = require('react');
const common = require('../common.js');
const createUsePaginatedQuery = ({ createResolver, resolve }, {
defaults: {
paginatedQueryFetchPolicy: defaultFetchPolicy,
paginatedQuerySuspense: defaultSuspense
}
}) => (fn, {
initialArgs,
fetchPolicy: hookFetchPolicy = defaultFetchPolicy,
merge,
retry,
skip = false,
suspense = defaultSuspense,
operationName
}) => {
const {
accessor: { query },
context,
selections
} = React.useMemo(
() => createResolver({
cachePolicy: common.translateFetchPolicy(hookFetchPolicy),
operationName,
retryPolicy: retry
}),
[hookFetchPolicy, operationName, retry]
);
const [state, setState] = React.useState({
args: initialArgs
});
if (suspense) {
if (state.promise) throw state.promise;
if (state.error) throw state.error;
}
const mergeData = React.useCallback(
(incoming) => {
var _a;
return (_a = merge == null ? void 0 : merge({
data: {
existing: state.data,
incoming
},
uniqBy: common.uniqBy,
sortBy: common.sortBy
})) != null ? _a : incoming;
},
[merge]
);
const fetchData = React.useCallback(
async (args, fetchPolicy = hookFetchPolicy) => {
const promise = resolve(({ query: query2 }) => fn(query2, args, common.coreHelpers), {
cachePolicy: common.translateFetchPolicy(fetchPolicy),
operationName,
retryPolicy: retry,
onSelect(selection, cache) {
context.select(selection, cache);
}
});
if (!context.shouldFetch) {
state.data = mergeData(fn(query, args, common.coreHelpers));
return state.data;
}
if (hookFetchPolicy === "cache-and-network" && context.hasCacheHit) {
state.data = mergeData(fn(query, args, common.coreHelpers));
}
state.promise = promise;
promise.finally(() => {
if (state.promise === promise) {
state.promise = void 0;
}
});
return promise;
},
[
context,
common.coreHelpers,
fn,
// fn almost guaranteed to change on every render
hookFetchPolicy,
mergeData,
operationName,
query,
retry
]
);
React.useState(() => {
if (skip) return setState(({ args }) => ({ args }));
const promise = fetchData(initialArgs);
promise.then(
(data) => {
setTimeout(() => {
setState(({ args }) => ({ args, data }));
}, 1e3);
},
(error) => {
setState(({ args }) => ({
args,
error: gqty.GQtyError.create(error)
}));
}
).finally(() => context.reset());
if (context.shouldFetch) {
if (suspense) {
throw promise;
} else {
setState(({ args }) => ({ args, promise }));
}
}
});
React.useEffect(() => {
if (skip || selections.size === 0) return;
return context.cache.subscribe(
[...selections].map((s) => s.cacheKeys.join(".")),
() => setState((state2) => ({ ...state2 }))
);
}, [selections.size]);
const fetchMore = React.useCallback(
async (newArgs, fetchPolicy) => {
const currentArgs = typeof newArgs === "function" ? newArgs({ existingData: state.data, existingArgs: state.args }) : newArgs != null ? newArgs : state.args;
try {
const promise = fetchData(currentArgs, fetchPolicy);
const data = await promise.then(mergeData);
setState(({ args }) => ({ args, data }));
return data;
} catch (e) {
const error = gqty.GQtyError.create(e);
setState(({ args }) => ({ args, error }));
throw error;
}
},
[fetchData]
);
React.useEffect(() => {
return context.cache.subscribe(
[...selections].map((s) => s.cacheKeys.join(".")),
() => {
setState((state2) => ({
...state2,
data: fn(query, state2.args, common.coreHelpers)
}));
}
);
}, [fn, state, selections.size]);
return React.useMemo(
() => Object.freeze({
args: state.args,
data: state.data,
fetchMore,
isLoading: state.promise !== void 0
}),
[state.args, state.data, fetchMore, state.promise]
);
};
exports.createUsePaginatedQuery = createUsePaginatedQuery;