Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

use-subscription

Package Overview
Dependencies
Maintainers
4
Versions
1837
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

use-subscription - npm Package Compare versions

Comparing version 0.0.0-experimental-ec372faef to 0.0.0-experimental-ed15d500-20241110

cjs/use-subscription.production.js

131

cjs/use-subscription.development.js

@@ -1,5 +0,6 @@

/** @license React vundefined
/**
* @license React
* use-subscription.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,115 +11,17 @@ * This source code is licensed under the MIT license found in the

'use strict';
if (process.env.NODE_ENV !== "production") {
(function() {
'use strict';
var _assign = require('object-assign');
var react = require('react');
//
// In order to avoid removing and re-adding subscriptions each time this hook is called,
// the parameters passed to this hook should be memoized in some way–
// either by wrapping the entire params object with useMemo()
// or by wrapping the individual callbacks with useCallback().
function useSubscription(_ref) {
var getCurrentValue = _ref.getCurrentValue,
subscribe = _ref.subscribe;
// Read the current value from our subscription.
// When this value changes, we'll schedule an update with React.
// It's important to also store the hook params so that we can check for staleness.
// (See the comment in checkForUpdates() below for more info.)
var _useState = react.useState(function () {
return {
getCurrentValue: getCurrentValue,
subscribe: subscribe,
value: getCurrentValue()
"use strict";
"production" !== process.env.NODE_ENV &&
(function () {
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
var shim = require("use-sync-external-store/shim");
exports.useSubscription = function (_ref) {
return shim.useSyncExternalStore(_ref.subscribe, _ref.getCurrentValue);
};
}),
state = _useState[0],
setState = _useState[1];
var valueToReturn = state.value; // If parameters have changed since our last render, schedule an update with its current value.
if (state.getCurrentValue !== getCurrentValue || state.subscribe !== subscribe) {
// If the subscription has been updated, we'll schedule another update with React.
// React will process this update immediately, so the old subscription value won't be committed.
// It is still nice to avoid returning a mismatched value though, so let's override the return value.
valueToReturn = getCurrentValue();
setState({
getCurrentValue: getCurrentValue,
subscribe: subscribe,
value: valueToReturn
});
} // Display the current value for this hook in React DevTools.
react.useDebugValue(valueToReturn); // It is important not to subscribe while rendering because this can lead to memory leaks.
// (Learn more at reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects)
// Instead, we wait until the commit phase to attach our handler.
//
// We intentionally use a passive effect (useEffect) rather than a synchronous one (useLayoutEffect)
// so that we don't stretch the commit phase.
// This also has an added benefit when multiple components are subscribed to the same source:
// It allows each of the event handlers to safely schedule work without potentially removing an another handler.
// (Learn more at https://codesandbox.io/s/k0yvr5970o)
react.useEffect(function () {
var didUnsubscribe = false;
var checkForUpdates = function () {
// It's possible that this callback will be invoked even after being unsubscribed,
// if it's removed as a result of a subscription event/update.
// In this case, React will log a DEV warning about an update from an unmounted component.
// We can avoid triggering that warning with this check.
if (didUnsubscribe) {
return;
} // We use a state updater function to avoid scheduling work for a stale source.
// However it's important to eagerly read the currently value,
// so that all scheduled work shares the same value (in the event of multiple subscriptions).
// This avoids visual "tearing" when a mutation happens during a (concurrent) render.
var value = getCurrentValue();
setState(function (prevState) {
// Ignore values from stale sources!
// Since we subscribe an unsubscribe in a passive effect,
// it's possible that this callback will be invoked for a stale (previous) subscription.
// This check avoids scheduling an update for that stale subscription.
if (prevState.getCurrentValue !== getCurrentValue || prevState.subscribe !== subscribe) {
return prevState;
} // Some subscriptions will auto-invoke the handler, even if the value hasn't changed.
// If the value hasn't changed, no update is needed.
// Return state as-is so React can bail out and avoid an unnecessary render.
if (prevState.value === value) {
return prevState;
}
return _assign({}, prevState, {
value: value
});
});
};
var unsubscribe = subscribe(checkForUpdates); // Because we're subscribing in a passive effect,
// it's possible that an update has occurred between render and our effect handler.
// Check for this and schedule an update if work has occurred.
checkForUpdates();
return function () {
didUnsubscribe = true;
unsubscribe();
};
}, [getCurrentValue, subscribe]); // Return the current value for our caller to use while rendering.
return valueToReturn;
}
exports.useSubscription = useSubscription;
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
})();
}
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/use-subscription.production.min.js');
module.exports = require('./cjs/use-subscription.production.js');
} else {
module.exports = require('./cjs/use-subscription.development.js');
}
{
"name": "use-subscription",
"description": "Reusable hooks",
"version": "0.0.0-experimental-ec372faef",
"version": "0.0.0-experimental-ed15d500-20241110",
"repository": {

@@ -13,3 +13,2 @@ "type": "git",

"README.md",
"build-info.json",
"index.js",

@@ -19,11 +18,11 @@ "cjs/"

"license": "MIT",
"dependencies": {
"object-assign": "^4.1.1"
},
"peerDependencies": {
"react": "0.0.0-experimental-ec372faef"
"react": "0.0.0-experimental-ed15d500-20241110"
},
"devDependencies": {
"rxjs": "^5.5.6"
},
"dependencies": {
"use-sync-external-store": "0.0.0-experimental-ed15d500-20241110"
}
}
# use-subscription
React hook that safely manages subscriptions in concurrent mode.
React Hook for subscribing to external data sources.
This utility can be used for subscriptions to a single value that are typically only read in one place and may update frequently (e.g. a component that subscribes to a geolocation API to show a dot on a map).
**You may now migrate to [`use-sync-external-store`](https://www.npmjs.com/package/use-sync-external-store) directly instead, which has the same API as [`React.useSyncExternalStore`](https://react.dev/reference/react/useSyncExternalStore). The `use-subscription` package is now a thin wrapper over `use-sync-external-store` and will not be updated further.**
## When should you NOT use this?
Most other cases have **better long-term solutions**:
* Redux/Flux stores should use the [context API](https://reactjs.org/docs/context.html) instead.
* I/O subscriptions (e.g. notifications) that update infrequently should use a mechanism like [`react-cache`](https://github.com/facebook/react/blob/master/packages/react-cache/README.md) instead.
* Complex libraries like Relay/Apollo should manage subscriptions manually with the same techniques which this library uses under the hood (as referenced [here](https://gist.github.com/bvaughn/d569177d70b50b58bff69c3c4a5353f3)) in a way that is most optimized for their library usage.
## Limitations in concurrent mode
`use-subscription` is safe to use in concurrent mode. However, [it achieves correctness by sometimes de-opting to synchronous mode](https://github.com/facebook/react/issues/13186#issuecomment-403959161), obviating the benefits of concurrent rendering. This is an inherent limitation of storing state outside of React's managed state queue and rendering in response to a change event.
The effect of de-opting to sync mode is that the main thread may periodically be blocked (in the case of CPU-bound work), and placeholders may appear earlier than desired (in the case of IO-bound work).
For **full compatibility** with concurrent rendering, including both **time-slicing** and **React Suspense**, the suggested longer-term solution is to move to one of the patterns described in the previous section.
## What types of subscriptions can this support?
This abstraction can handle a variety of subscription types, including:
* Event dispatchers like `HTMLInputElement`.
* Custom pub/sub components like Relay's `FragmentSpecResolver`.
* Observable types like RxJS `BehaviorSubject` and `ReplaySubject`. (Types like RxJS `Subject` or `Observable` are not supported, because they provide no way to read the "current" value after it has been emitted.)
Note that JavaScript promises are also **not supported** because they provide no way to synchronously read the "current" value.
# Installation

@@ -32,0 +8,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc