pgadmin4/web/pgadmin/static/js/SchemaView/hooks/useSchemaStateSubscriber.js

93 lines
2.1 KiB
JavaScript

/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React from 'react';
/////////
//
// A class to handle the ScheamState subscription for a control to avoid
// rendering multiple times.
//
class SubscriberManager {
constructor(refreshKeyCallback) {
this.mounted = true;
this.callback = refreshKeyCallback;
this.unsubscribers = new Set();
this._id = Date.now();
}
add(schemaState, accessPath, kind, callback) {
if (!schemaState) return;
callback = callback || (() => this.signal());
return this._add(schemaState.subscribe(accessPath, callback, kind));
}
_add(unsubscriber) {
if (!unsubscriber) return;
// Avoid reinsertion of same unsubscriber.
if (this.unsubscribers.has(unsubscriber)) return;
this.unsubscribers.add(unsubscriber);
return () => this.remove(unsubscriber);
}
remove(unsubscriber) {
if (!unsubscriber) return;
if (!this.unsubscribers.has(unsubscriber)) return;
this.unsubscribers.delete(unsubscriber);
unsubscriber();
}
signal() {
// Do nothing - if already work is in progress.
if (!this.mounted) return;
this.mounted = false;
this.release();
this.callback(Date.now());
}
release () {
const unsubscribers = this.unsubscribers;
this.unsubscribers = new Set();
this.mounted = true;
setTimeout(() => {
Set.prototype.forEach.call(
unsubscribers, (unsubscriber) => unsubscriber()
);
}, 0);
}
mount() {
this.mounted = true;
}
}
export function useSchemaStateSubscriber(refreshKeyCallback) {
const subscriberManager = React.useRef(null);
React.useEffect(() => {
if (!subscriberManager.current) return;
return () => {
subscriberManager.current?.release();
};
}, []);
if (!subscriberManager.current)
subscriberManager.current = new SubscriberManager(refreshKeyCallback);
else
subscriberManager.current.mount();
return subscriberManager;
}