UNPKG

vue-redux-hooks

Version:
219 lines (205 loc) 9.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue-demi'), require('@reduxjs/toolkit/query')) : typeof define === 'function' && define.amd ? define(['exports', 'vue-demi', '@reduxjs/toolkit/query'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VueReduxHooks = {}, global.VueDemi, global.query)); }(this, (function (exports, vueDemi, query) { 'use strict'; const ReduxStore = Symbol('redux'); const useStore = () => { const store = vueDemi.inject(ReduxStore); assert(store, 'Warning: no redux store was provided.\n\nPlease provide store preferably with vue install\n\napp.provide(ReduxStore, store)\n\nLearn more about vue-redux-hooks: https://github.com/PatrykWalach/vue-redux-hooks'); return store; }; function assert(condition, message) { if (!condition) { // console.error(message) throw message; } } const useSelector = (select) => { const { subscribe, getState } = useStore(); const state = vueDemi.shallowRef(getState()); const unsubscribe = subscribe(() => { const nextState = getState(); state.value = nextState; }); vueDemi.onBeforeUnmount(unsubscribe); return vueDemi.computed(() => select(state.value)); }; const useDispatch = () => { const { dispatch } = useStore(); return dispatch; }; function refToReactive(result, keys) { return vueDemi.reactive(Object.fromEntries(keys.map((key) => [key, vueDemi.computed(() => result.value[key])]))); } const createUseMutation = (endpoint) => () => { const dispatch = useDispatch(); const promiseRef = vueDemi.shallowRef(); // onBeforeUnmount(() => { // promiseRef.value && promiseRef.value.unsubscribe() // }) vueDemi.watchEffect((onCleanup) => { const promise = promiseRef.value; onCleanup(() => { // promise && promise.unsubscribe() promise?.unsubscribe(); }); }); const triggerMutation = (arg) => { // promiseRef.value && promiseRef.value.unsubscribe() const promise = dispatch(endpoint.initiate(arg)); promiseRef.value = promise; return promise; }; const requestId = vueDemi.computed(() => promiseRef.value && promiseRef.value.requestId); const mutationSelector = vueDemi.computed(() => endpoint.select(requestId.value || query.skipToken)); const currentState = useSelector((state) => mutationSelector.value(state)); return [ triggerMutation, refToReactive(currentState, [ 'originalArgs', 'data', 'error', 'endpointName', 'fulfilledTimeStamp', 'isUninitialized', 'isLoading', 'isSuccess', 'isError', 'startedTimeStamp', ]), ]; }; const createUseQueryState = (endpoint) => (arg, { skip = false } = {}) => { const options = vueDemi.reactive({ skip, arg }); const stableArg = vueDemi.computed(() => (options.skip ? query.skipToken : options.arg)); const selector = vueDemi.computed(() => endpoint.select(stableArg.value)); const result = useSelector((state) => selector.value(state)); return refToReactive(result, [ 'isUninitialized', 'isLoading', 'isSuccess', 'isError', 'data', 'error', 'status', 'startedTimeStamp', 'requestId', 'originalArgs', 'fulfilledTimeStamp', 'endpointName', ]); }; const createUseQuerySubscription = (endpoint) => (arg, { skip = false, pollingInterval = 0, ...otherOptions } = {}) => { const options = vueDemi.reactive({ skip, arg, pollingInterval, ...otherOptions, }); const stableArg = vueDemi.computed(() => (options.skip ? query.skipToken : options.arg)); const refetchOnMountOrArgChange = vueDemi.toRef(options, 'refetchOnMountOrArgChange'); const stableSubscriptionOptions = vueDemi.computed(() => ({ refetchOnReconnect: options.refetchOnReconnect, refetchOnFocus: options.refetchOnFocus, pollingInterval: options.pollingInterval, })); const promiseRef = vueDemi.shallowRef(undefined); const dispatch = useDispatch(); vueDemi.watch([stableArg, refetchOnMountOrArgChange, stableSubscriptionOptions], ([stableArg, forceRefetch, subscriptionOptions], _, onCleanup) => { const lastPromise = promiseRef.value; if (stableArg === query.skipToken) { lastPromise && lastPromise.unsubscribe(); promiseRef.value = undefined; return; } const lastSubscriptionOptions = lastPromise && lastPromise.subscriptionOptions; if (!lastPromise || lastPromise.arg !== stableArg) { lastPromise && lastPromise.unsubscribe(); const promise = dispatch(endpoint.initiate(stableArg, { subscriptionOptions, forceRefetch, })); promiseRef.value = promise; return; } if (stableSubscriptionOptions !== lastSubscriptionOptions) { lastPromise.updateSubscriptionOptions(subscriptionOptions); } }, { immediate: true }); vueDemi.onBeforeUnmount(() => { promiseRef.value && promiseRef.value.unsubscribe(); }); return { refetch() { promiseRef.value && promiseRef.value.refetch(); }, }; }; const createUseQuery = (endpoint) => { const useQueryState = createUseQueryState(endpoint); const useQuerySubscription = createUseQuerySubscription(endpoint); return (arg, options) => { return vueDemi.reactive({ ...vueDemi.toRefs(useQueryState(arg, options)), ...useQuerySubscription(arg, options), }); }; }; var DefinitionType; (function (DefinitionType) { DefinitionType["query"] = "query"; DefinitionType["mutation"] = "mutation"; })(DefinitionType || (DefinitionType = {})); function isQueryDefinition(e) { return e.type === DefinitionType.query; } function isMutationDefinition(e) { return e.type === DefinitionType.mutation; } const vueHooksModuleName = Symbol('vueHooksModule'); const capitalize = (str) => str[0].toUpperCase() + str.substr(1); const vueHooksModule = () => ({ name: vueHooksModuleName, init(api) { return { injectEndpoint(endpointName, definition) { const endpoint = api.endpoints[endpointName]; const capitalizedEndpointName = capitalize(endpointName); if (isQueryDefinition(definition)) { const queryHooks = createQueryHooks(endpoint); Object.assign(endpoint, queryHooks); Object.assign(api, { [`use${capitalizedEndpointName}Query`]: queryHooks.useQuery, // [`useLazy${capitalizedEndpointName}Query`]: queryHooks.useLazyQuery }); return; } if (isMutationDefinition(definition)) { const useMutation = createUseMutation(endpoint); Object.assign(endpoint, { useMutation, }); Object.assign(api, { [`use${capitalizedEndpointName}Mutation`]: useMutation, }); return; } }, }; }, }); const createApi = query.buildCreateApi(query.coreModule(), vueHooksModule()); const createQueryHooks = (endpoint) => ({ useQueryState: createUseQueryState(endpoint), useQuery: createUseQuery(endpoint), useQuerySubscription: createUseQuerySubscription(endpoint), }); exports.ReduxStore = ReduxStore; exports.createApi = createApi; exports.useDispatch = useDispatch; exports.useSelector = useSelector; exports.useStore = useStore; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=vue-redux-hooks.global.js.map