UNPKG

react-query

Version:

Hooks for managing, caching and syncing asynchronous and remote data in React

164 lines (131 loc) 5.06 kB
"use strict"; exports.__esModule = true; exports.QueriesObserver = void 0; var _utils = require("./utils"); var _notifyManager = require("./notifyManager"); var _queryObserver = require("./queryObserver"); var _subscribable = require("./subscribable"); class QueriesObserver extends _subscribable.Subscribable { constructor(client, queries) { super(); this.client = client; this.queries = []; this.result = []; this.observers = []; this.observersMap = {}; if (queries) { this.setQueries(queries); } } onSubscribe() { if (this.listeners.length === 1) { this.observers.forEach(observer => { observer.subscribe(result => { this.onUpdate(observer, result); }); }); } } onUnsubscribe() { if (!this.listeners.length) { this.destroy(); } } destroy() { this.listeners = []; this.observers.forEach(observer => { observer.destroy(); }); } setQueries(queries, notifyOptions) { this.queries = queries; _notifyManager.notifyManager.batch(() => { const prevObservers = this.observers; const newObserverMatches = this.findMatchingObservers(this.queries); // set options for the new observers to notify of changes newObserverMatches.forEach(match => match.observer.setOptions(match.defaultedQueryOptions, notifyOptions)); const newObservers = newObserverMatches.map(match => match.observer); const newObserversMap = Object.fromEntries(newObservers.map(observer => [observer.options.queryHash, observer])); const newResult = newObservers.map(observer => observer.getCurrentResult()); const hasIndexChange = newObservers.some((observer, index) => observer !== prevObservers[index]); if (prevObservers.length === newObservers.length && !hasIndexChange) { return; } this.observers = newObservers; this.observersMap = newObserversMap; this.result = newResult; if (!this.hasListeners()) { return; } (0, _utils.difference)(prevObservers, newObservers).forEach(observer => { observer.destroy(); }); (0, _utils.difference)(newObservers, prevObservers).forEach(observer => { observer.subscribe(result => { this.onUpdate(observer, result); }); }); this.notify(); }); } getCurrentResult() { return this.result; } getOptimisticResult(queries) { return this.findMatchingObservers(queries).map(match => match.observer.getOptimisticResult(match.defaultedQueryOptions)); } findMatchingObservers(queries) { const prevObservers = this.observers; const defaultedQueryOptions = queries.map(options => this.client.defaultQueryOptions(options)); const matchingObservers = defaultedQueryOptions.flatMap(defaultedOptions => { const match = prevObservers.find(observer => observer.options.queryHash === defaultedOptions.queryHash); if (match != null) { return [{ defaultedQueryOptions: defaultedOptions, observer: match }]; } return []; }); const matchedQueryHashes = matchingObservers.map(match => match.defaultedQueryOptions.queryHash); const unmatchedQueries = defaultedQueryOptions.filter(defaultedOptions => !matchedQueryHashes.includes(defaultedOptions.queryHash)); const unmatchedObservers = prevObservers.filter(prevObserver => !matchingObservers.some(match => match.observer === prevObserver)); const getObserver = options => { const defaultedOptions = this.client.defaultQueryOptions(options); const currentObserver = this.observersMap[defaultedOptions.queryHash]; return currentObserver != null ? currentObserver : new _queryObserver.QueryObserver(this.client, defaultedOptions); }; const newOrReusedObservers = unmatchedQueries.map((options, index) => { if (options.keepPreviousData) { // return previous data from one of the observers that no longer match const previouslyUsedObserver = unmatchedObservers[index]; if (previouslyUsedObserver !== undefined) { return { defaultedQueryOptions: options, observer: previouslyUsedObserver }; } } return { defaultedQueryOptions: options, observer: getObserver(options) }; }); const sortMatchesByOrderOfQueries = (a, b) => defaultedQueryOptions.indexOf(a.defaultedQueryOptions) - defaultedQueryOptions.indexOf(b.defaultedQueryOptions); return matchingObservers.concat(newOrReusedObservers).sort(sortMatchesByOrderOfQueries); } onUpdate(observer, result) { const index = this.observers.indexOf(observer); if (index !== -1) { this.result = (0, _utils.replaceAt)(this.result, index, result); this.notify(); } } notify() { _notifyManager.notifyManager.batch(() => { this.listeners.forEach(listener => { listener(this.result); }); }); } } exports.QueriesObserver = QueriesObserver;