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

use-context-selector

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

use-context-selector - npm Package Compare versions

Comparing version 2.0.0-alpha.6 to 2.0.0-alpha.7

2

dist/index.modern.js

@@ -1,2 +0,2 @@

import{unstable_createMutableSource as e,createContext as r,memo as t,useContext as n,useCallback as o,unstable_useMutableSource as c,useRef as u,useMemo as s,createElement as i,useLayoutEffect as a,useEffect as d}from"react";import{unstable_runWithPriority as f,unstable_NormalPriority as l,unstable_UserBlockingPriority as v}from"scheduler";const p="undefined"==typeof window||/ServerSideRendering/.test(window.navigator&&window.navigator.userAgent)?d:a,w=Symbol(),m=Symbol(),h=new WeakMap,g=e=>e;function x(n){const o=e({current:n},()=>n),c=r({[w]:o});var a;return c.Provider=(a=c.Provider,t(({value:r,children:t})=>{const n=u({v:r,l:new Set});p(()=>{n.current.v=r,f(l,()=>{n.current.l.forEach(e=>e())})});const o=s(()=>({[w]:e(n,()=>n.current.v)}),[]);return i(a,{value:o},t)})),delete c.Consumer,c}const S=(e,r)=>{const t=e.current.l;return t.add(r),()=>t.delete(r)};function y(e,r=g){const{[w]:t}=n(e);if("production"!==process.env.NODE_ENV&&!t)throw new Error("This useContext requires special context for selector support");const u=o(e=>{const t=r(e.current.v);if("function"==typeof t){if(h.has(t))return h.get(t);const e={[m]:t};return h.set(t,e),e}return t},[r]),s=c(t,u,S);return s&&s[m]?s[m]:s}function C(e){return(...r)=>f(v,()=>e(...r))}export{x as createContext,y as useContext,C as wrapCallbackWithPriority};
import{createContext as r,unstable_createMutableSource as e,useContext as n,useCallback as t,unstable_useMutableSource as o,useRef as s,useMemo as c,createElement as u,useLayoutEffect as i,useEffect as l}from"react";import{unstable_NormalPriority as a,unstable_getCurrentPriorityLevel as p,unstable_runWithPriority as d,unstable_ImmediatePriority as f}from"scheduler";const v="undefined"==typeof window||/ServerSideRendering/.test(window.navigator&&window.navigator.userAgent)?l:i,w=Symbol(),S=Symbol(),h=Symbol(),m=new WeakMap,g=r=>r,x=r=>{const n={current:{v:-1,p:r,s:r,l:new Set}};return e(n,()=>n.current.v)};function y(n){const t=r({[w]:x(n),[S]:r=>r()});var o;return t.Provider=(o=t.Provider,({value:r,children:n})=>{const t=s({v:0,p:r,s:r,l:new Set}),i=s(a),l=c(()=>({[w]:e(t,()=>t.current.v),[S]:r=>(i.current=p(),d(f,r))}),[]);return v(()=>{null!==l[w]._workInProgressVersionSecondary?t.current.s=r:t.current.p=r,t.current.v+=1,d(i.current,()=>{t.current.l.forEach(r=>r())}),i.current=a}),u(o,{value:l},n)}),delete t.Consumer,t}const E=(r,e)=>{const n=r.current.l;return n.add(e),()=>n.delete(e)};function C(r,e=g){const{[w]:s}=n(r);if("production"!==process.env.NODE_ENV&&!s)throw new Error("This useContext requires special context for selector support");const c=t(r=>{const n=e(null!==s._workInProgressVersionSecondary?r.current.s:r.current.p);if("function"==typeof n){if(m.has(n))return m.get(n);const r={[h]:n};return m.set(n,r),r}return n},[e,s]),u=o(s,c,E);return u&&u[h]?u[h]:u}function N(r){const{[S]:e}=n(r);if("production"!==process.env.NODE_ENV&&!e)throw new Error("This useContext requires special context for selector support");return e}export{y as createContext,C as useContext,N as useContextUpdate};
//# sourceMappingURL=index.modern.js.map

@@ -1,2 +0,2 @@

!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("react"),require("scheduler")):"function"==typeof define&&define.amd?define(["exports","react","scheduler"],r):r((e=e||self).useContextSelector={},e.react,e.scheduler)}(this,function(e,r,t){var n="undefined"==typeof window||/ServerSideRendering/.test(window.navigator&&window.navigator.userAgent)?r.useEffect:r.useLayoutEffect,u=Symbol(),o=Symbol(),i=new WeakMap,c=function(e){return e},a=function(e,r){var t=e.current.l;return t.add(r),function(){return t.delete(r)}};e.createContext=function(e){var o,i,c=r.unstable_createMutableSource({current:e},function(){return e}),a=r.createContext(((o={})[u]=c,o));return a.Provider=(i=a.Provider,r.memo(function(e){var o,c=e.value,a=e.children,f=r.useRef(((o={}).v=c,o.l=new Set,o));n(function(){f.current.v=c,t.unstable_runWithPriority(t.unstable_NormalPriority,function(){f.current.l.forEach(function(e){return e()})})});var l=r.useMemo(function(){var e;return(e={})[u]=r.unstable_createMutableSource(f,function(){return f.current.v}),e},[]);return r.createElement(i,{value:l},a)})),delete a.Consumer,a},e.useContext=function(e,t){void 0===t&&(t=c);var n=r.useContext(e)[u];if("production"!==process.env.NODE_ENV&&!n)throw new Error("This useContext requires special context for selector support");var f=r.useCallback(function(e){var r=t(e.current.v);if("function"==typeof r){var n;if(i.has(r))return i.get(r);var u=((n={})[o]=r,n);return i.set(r,u),u}return r},[t]),l=r.unstable_useMutableSource(n,f,a);return l&&l[o]?l[o]:l},e.wrapCallbackWithPriority=function(e){return function(){var r=arguments;return t.unstable_runWithPriority(t.unstable_UserBlockingPriority,function(){return e.apply(void 0,[].slice.call(r))})}}});
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("react"),require("scheduler")):"function"==typeof define&&define.amd?define(["exports","react","scheduler"],r):r((e=e||self).useContextSelector={},e.react,e.scheduler)}(this,function(e,r,t){var n="undefined"==typeof window||/ServerSideRendering/.test(window.navigator&&window.navigator.userAgent)?r.useEffect:r.useLayoutEffect,u=Symbol(),o=Symbol(),i=Symbol(),c=new WeakMap,s=function(e){return e},a=function(e,r){var t=e.current.l;return t.add(r),function(){return t.delete(r)}};e.createContext=function(e){var i,c,s=r.createContext(((i={})[u]=function(e){var t={current:{v:-1,p:e,s:e,l:new Set}};return r.unstable_createMutableSource(t,function(){return t.current.v})}(e),i[o]=function(e){return e()},i));return s.Provider=(c=s.Provider,function(e){var i=e.value,s=e.children,a=r.useRef({v:0,p:i,s:i,l:new Set}),f=r.useRef(t.unstable_NormalPriority),l=r.useMemo(function(){var e;return(e={})[u]=r.unstable_createMutableSource(a,function(){return a.current.v}),e[o]=function(e){return f.current=t.unstable_getCurrentPriorityLevel(),t.unstable_runWithPriority(t.unstable_ImmediatePriority,e)},e},[]);return n(function(){null!==l[u]._workInProgressVersionSecondary?a.current.s=i:a.current.p=i,a.current.v+=1,t.unstable_runWithPriority(f.current,function(){a.current.l.forEach(function(e){return e()})}),f.current=t.unstable_NormalPriority}),r.createElement(c,{value:l},s)}),delete s.Consumer,s},e.useContext=function(e,t){void 0===t&&(t=s);var n=r.useContext(e)[u];if("production"!==process.env.NODE_ENV&&!n)throw new Error("This useContext requires special context for selector support");var o=r.useCallback(function(e){var r=t(null!==n._workInProgressVersionSecondary?e.current.s:e.current.p);if("function"==typeof r){var u;if(c.has(r))return c.get(r);var o=((u={})[i]=r,u);return c.set(r,o),o}return r},[t,n]),f=r.unstable_useMutableSource(n,o,a);return f&&f[i]?f[i]:f},e.useContextUpdate=function(e){var t=r.useContext(e)[o];if("production"!==process.env.NODE_ENV&&!t)throw new Error("This useContext requires special context for selector support");return t}});
//# sourceMappingURL=index.umd.js.map

@@ -23,15 +23,13 @@ import { ComponentType } from 'react';

export declare function useContext<Value, Selected>(context: Context<Value>, selector: (value: Value) => Selected): Selected;
declare type AnyCallback = (...args: any) => any;
/**
* A utility function to wrap a callback function with higher priority
* This hook returns an update function that accepts a thunk function
*
* Use this for a callback that will change a value,
* which will be fed into context provider.
* Use this for a function that will change a value.
*
* @example
* import { wrapCallbackWithPriority } from 'use-context-selector';
* import { useContextUpdate } from 'use-context-selector';
*
* const wrappedCallback = wrapCallbackWithPriority(callback);
* const update = useContextUpdate();
* update(() => setState(...));
*/
export declare function wrapCallbackWithPriority<Callback extends AnyCallback>(callback: Callback): Callback;
export {};
export declare function useContextUpdate(context: Context<unknown>): <T>(thunk: () => T) => T;
{
"name": "use-context-selector",
"description": "React useContext with selector support in userland",
"version": "2.0.0-alpha.6",
"version": "2.0.0-alpha.7",
"publishConfig": {

@@ -6,0 +6,0 @@ "tag": "next"

@@ -157,12 +157,11 @@ # use-context-selector

### wrapCallbackWithPriority
### useContextUpdate
A utility function to wrap a callback function with higher priority
This hook returns an update function that accepts a thunk function
Use this for a callback that will change a value,
which will be fed into context provider.
Use this for a function that will change a value.
#### Parameters
- `callback` **Callback**
- `context` **Context&lt;any>**

@@ -172,5 +171,6 @@ #### Examples

```javascript
import { wrapCallbackWithPriority } from 'use-context-selector';
import { useContextUpdate } from 'use-context-selector';
const wrappedCallback = wrapCallbackWithPriority(callback);
const update = useContextUpdate();
update(() => setState(...));
```

@@ -181,3 +181,2 @@

- In order to stop propagation, `children` of a context provider has to be either created outside of the provider or memoized with `React.memo`.
- Provider trigger re-renders only if the context value is referentially changed.
- Neither context consumers or class components are supported.

@@ -184,0 +183,0 @@ - The [stale props](https://react-redux.js.org/api/hooks#stale-props-and-zombie-children) issue can't be solved in userland.

@@ -13,3 +13,2 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */

unstable_createMutableSource as createMutableSource,
memo,
useCallback,

@@ -25,5 +24,6 @@ useContext as useContextOrig,

import {
unstable_UserBlockingPriority as UserBlockingPriority,
unstable_ImmediatePriority as ImmediatePriority,
unstable_NormalPriority as NormalPriority,
unstable_runWithPriority as runWithPriority,
unstable_getCurrentPriorityLevel as getCurrentPriorityLevel,
} from 'scheduler';

@@ -39,8 +39,7 @@

const SOURCE_SYMBOL = Symbol();
const VALUE_PROP = 'v';
const LISTENERS_PROP = 'l';
const UPDATE_SYMBOL = Symbol();
const FUNCTION_SYNBOL = Symbol();
const FUNCTION_SYMBOL = Symbol();
// eslint-disable-next-line @typescript-eslint/ban-types
const functionMap = new WeakMap<Function, { [FUNCTION_SYNBOL]: Function }>();
const functionMap = new WeakMap<Function, { [FUNCTION_SYMBOL]: Function }>();

@@ -50,4 +49,12 @@ // @ts-ignore

[SOURCE_SYMBOL]: any;
[UPDATE_SYMBOL]: <T>(thunk: () => T) => T;
};
type RefValue<Value> = MutableRefObject<{
v: number; // "v" = version
p: Value; // "p" = primary value
s: Value; // "s" = secondary value
l: Set<() => void>; // "l" = listeners
}>;
export interface Context<Value> {

@@ -60,18 +67,31 @@ Provider: ComponentType<{ value: Value }>;

const RefProvider: FC<{ value: Value }> = ({ value, children }) => {
const ref = useRef({
[VALUE_PROP]: value,
[LISTENERS_PROP]: new Set<() => void>(),
const ref: RefValue<Value> = useRef({
v: 0, // "v" = version
p: value, // "p" = primary value
s: value, // "s" = secondary value
l: new Set<() => void>(), // "l" = listeners
});
const priorityRef = useRef(NormalPriority);
const contextValue = useMemo(() => ({
[SOURCE_SYMBOL]: createMutableSource(ref, () => ref.current.v),
[UPDATE_SYMBOL]: <T>(thunk: () => T) => {
priorityRef.current = getCurrentPriorityLevel();
return runWithPriority(ImmediatePriority, thunk);
},
}), []);
useIsomorphicLayoutEffect(() => {
ref.current[VALUE_PROP] = value;
runWithPriority(NormalPriority, () => {
ref.current[LISTENERS_PROP].forEach((listener) => listener());
if (contextValue[SOURCE_SYMBOL]._workInProgressVersionSecondary !== null) {
ref.current.s = value; // update secondary value
} else {
ref.current.p = value; // update primary value
}
ref.current.v += 1; // increment version
runWithPriority(priorityRef.current, () => {
ref.current.l.forEach((listener) => listener());
});
priorityRef.current = NormalPriority;
});
const contextValue = useMemo(() => ({
[SOURCE_SYMBOL]: createMutableSource(ref, () => ref.current[VALUE_PROP]),
}), []);
return createElement(ProviderOrig, { value: contextValue }, children);
};
return memo(RefProvider);
return RefProvider;
};

@@ -81,2 +101,14 @@

const createDefaultSource = <Value>(defaultValue: Value) => {
const ref: RefValue<Value> = {
current: {
v: -1, // "v" = version
p: defaultValue, // "p" = primary value
s: defaultValue, // "s" = secondary value
l: new Set<() => void>(), // "l" = listeners
},
};
return createMutableSource(ref, () => ref.current.v);
};
/**

@@ -95,4 +127,6 @@ * This creates a special context for selector-enabled `useContext`.

export function createContext<Value>(defaultValue: Value) {
const source = createMutableSource({ current: defaultValue }, () => defaultValue);
const context = createContextOrig({ [SOURCE_SYMBOL]: source });
const context = createContextOrig<ContextValue<Value>>({
[SOURCE_SYMBOL]: createDefaultSource(defaultValue),
[UPDATE_SYMBOL]: (thunk) => thunk(),
});
(context as unknown as Context<Value>).Provider = createProvider(context.Provider);

@@ -104,6 +138,6 @@ delete context.Consumer; // no support for Consumer

const subscribe = (
ref: MutableRefObject<{ [LISTENERS_PROP]: Set<() => void> }>,
ref: RefValue<unknown>,
callback: () => void,
) => {
const listeners = ref.current[LISTENERS_PROP];
const listeners = ref.current.l;
listeners.add(callback);

@@ -147,4 +181,7 @@ return () => listeners.delete(callback);

const getSnapshot = useCallback(
(ref: MutableRefObject<{ [VALUE_PROP]: Value }>) => {
const selected = selector(ref.current[VALUE_PROP]);
(ref: RefValue<Value>) => {
const value = source._workInProgressVersionSecondary !== null
? ref.current.s // "s" = secondary value
: ref.current.p; // "p" = primary value
const selected = selector(value);
if (typeof selected === 'function') {

@@ -154,3 +191,3 @@ if (functionMap.has(selected)) {

}
const wrappedFunction = { [FUNCTION_SYNBOL]: selected };
const wrappedFunction = { [FUNCTION_SYMBOL]: selected };
functionMap.set(selected, wrappedFunction);

@@ -161,7 +198,7 @@ return wrappedFunction;

},
[selector],
[selector, source],
);
const snapshot = useMutableSource(source, getSnapshot, subscribe);
if (snapshot && (snapshot as { [FUNCTION_SYNBOL]: unknown })[FUNCTION_SYNBOL]) {
return snapshot[FUNCTION_SYNBOL];
if (snapshot && (snapshot as { [FUNCTION_SYMBOL]: unknown })[FUNCTION_SYMBOL]) {
return snapshot[FUNCTION_SYMBOL];
}

@@ -171,20 +208,25 @@ return snapshot;

type AnyCallback = (...args: any) => any;
/**
* A utility function to wrap a callback function with higher priority
* This hook returns an update function that accepts a thunk function
*
* Use this for a callback that will change a value,
* which will be fed into context provider.
* Use this for a function that will change a value.
*
* @example
* import { wrapCallbackWithPriority } from 'use-context-selector';
* import { useContextUpdate } from 'use-context-selector';
*
* const wrappedCallback = wrapCallbackWithPriority(callback);
* const update = useContextUpdate();
* update(() => setState(...));
*/
export function wrapCallbackWithPriority<Callback extends AnyCallback>(callback: Callback) {
const callbackWithPriority = (...args: any) => (
runWithPriority(UserBlockingPriority, () => callback(...args))
export function useContextUpdate(
context: Context<unknown>,
) {
const { [UPDATE_SYMBOL]: update } = useContextOrig(
context as unknown as ContextOrig<ContextValue<unknown>>,
);
return callbackWithPriority as Callback;
if (process.env.NODE_ENV !== 'production') {
if (!update) {
throw new Error('This useContext requires special context for selector support');
}
}
return update;
}

Sorry, the diff of this file is not supported yet

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