vue-redux-hooks
Version:
Redux hooks for Vue
214 lines (200 loc) • 7.83 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var vueDemi = require('vue-demi');
var query = require('@reduxjs/toolkit/query');
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) {
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();
});
});
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;
//# sourceMappingURL=vue-redux-hooks.cjs.js.map