@wendellhu/redi
Advanced tools
Comparing version 0.14.0 to 0.15.0
@@ -171,2 +171,11 @@ (function (global, factory) { | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
/** | ||
@@ -176,9 +185,9 @@ * unwrap an observable value, return it to the component for rendering, and | ||
* | ||
* **IMPORTANT**. Parent and child components should not subscribe to the same | ||
* **IMPORTANT**. Parent and child components better not subscribe to the same | ||
* observable, otherwise unnecessary re-render would be triggered. Instead, the | ||
* top-most component should subscribe and pass value of the observable to | ||
* its offspring, by props or context. | ||
* its offspring, by props or context. Please consider using `useDependencyContext` and | ||
* `useDependencyContextValue` in this case. | ||
* | ||
* If you have to do that, consider using `useDependencyContext` and | ||
* `useDependencyContextValue` instead. | ||
* @deprecated Please use `useObservable` instead. | ||
*/ | ||
@@ -196,3 +205,56 @@ function useDependencyValue(depValue$, defaultValue) { | ||
} | ||
function unwrap(o) { | ||
if (typeof o === 'function') { | ||
return o(); | ||
} | ||
return o; | ||
} | ||
/** | ||
* Subscribe to an observable and return its value. The component will re-render when the observable emits a new value. | ||
* | ||
* @param observable An observable or a function that returns an observable | ||
* @param defaultValue The default value of the observable. It the `observable` can omit an initial value, this value will be neglected. | ||
* @param shouldHaveSyncValue If the observable should have a sync value. If it does not have a sync value, an error will be thrown. | ||
* @param deps A dependency array to decide if we should re-subscribe when the `observable` is a function. | ||
* @returns | ||
*/ | ||
function useObservable(observable, defaultValue, shouldHaveSyncValue, deps) { | ||
if (typeof observable === 'function' && !deps) { | ||
throw new redi.RediError("Expected deps to be provided when observable is a function!"); | ||
} | ||
var observableRef = React.useRef(null); | ||
var initializedRef = React.useRef(false); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
var destObservable = React.useMemo(function () { return observable; }, __spreadArray([], (typeof deps !== 'undefined' ? deps : [observable]), true)); | ||
// This state is only for trigger React to re-render. We do not use `setValue` directly because it may cause | ||
// memory leaking. | ||
var _a = React.useState(0), _ = _a[0], setRenderCounter = _a[1]; | ||
var valueRef = React.useRef((function () { | ||
var innerDefaultValue; | ||
if (destObservable) { | ||
var sub = unwrap(destObservable).subscribe(function (value) { | ||
initializedRef.current = true; | ||
innerDefaultValue = value; | ||
}); | ||
sub.unsubscribe(); | ||
} | ||
return innerDefaultValue !== null && innerDefaultValue !== void 0 ? innerDefaultValue : defaultValue; | ||
})()); | ||
React.useEffect(function () { | ||
var subscription = null; | ||
if (destObservable) { | ||
observableRef.current = unwrap(destObservable); | ||
subscription = observableRef.current.subscribe(function (value) { | ||
valueRef.current = value; | ||
setRenderCounter(function (prev) { return prev + 1; }); | ||
}); | ||
} | ||
return function () { return subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe(); }; | ||
}, [destObservable]); | ||
if (shouldHaveSyncValue && !initializedRef.current) { | ||
throw new Error('Expect `shouldHaveSyncValue` but not getting a sync value!'); | ||
} | ||
return valueRef.current; | ||
} | ||
/** | ||
* subscribe to a signal that emits whenever data updates and re-render | ||
@@ -254,2 +316,3 @@ * | ||
exports.useInjector = useInjector; | ||
exports.useObservable = useObservable; | ||
exports.useUpdateBinder = useUpdateBinder; | ||
@@ -256,0 +319,0 @@ |
@@ -7,11 +7,17 @@ import { ReactNode } from 'react'; | ||
* | ||
* **IMPORTANT**. Parent and child components should not subscribe to the same | ||
* **IMPORTANT**. Parent and child components better not subscribe to the same | ||
* observable, otherwise unnecessary re-render would be triggered. Instead, the | ||
* top-most component should subscribe and pass value of the observable to | ||
* its offspring, by props or context. | ||
* its offspring, by props or context. Please consider using `useDependencyContext` and | ||
* `useDependencyContextValue` in this case. | ||
* | ||
* If you have to do that, consider using `useDependencyContext` and | ||
* `useDependencyContextValue` instead. | ||
* @deprecated Please use `useObservable` instead. | ||
*/ | ||
export declare function useDependencyValue<T>(depValue$: Observable<T>, defaultValue?: T): T | undefined; | ||
type ObservableOrFn<T> = Observable<T> | (() => Observable<T>); | ||
type Nullable<T> = T | undefined | null; | ||
export declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>): T | undefined; | ||
export declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue: T): T; | ||
export declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue: undefined, shouldHaveSyncValue: true, deps?: any[]): T; | ||
export declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue?: undefined, shouldHaveSyncValue?: true, deps?: any[]): T | undefined; | ||
/** | ||
@@ -35,1 +41,2 @@ * subscribe to a signal that emits whenever data updates and re-render | ||
export declare function useDependencyContextValue<T>(depValue$: Observable<T>): T | undefined; | ||
export {}; |
@@ -0,1 +1,10 @@ | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
import React, { useEffect, useState, createContext, useMemo, useContext, useCallback, useRef, } from 'react'; | ||
@@ -8,9 +17,9 @@ import { BehaviorSubject } from 'rxjs'; | ||
* | ||
* **IMPORTANT**. Parent and child components should not subscribe to the same | ||
* **IMPORTANT**. Parent and child components better not subscribe to the same | ||
* observable, otherwise unnecessary re-render would be triggered. Instead, the | ||
* top-most component should subscribe and pass value of the observable to | ||
* its offspring, by props or context. | ||
* its offspring, by props or context. Please consider using `useDependencyContext` and | ||
* `useDependencyContextValue` in this case. | ||
* | ||
* If you have to do that, consider using `useDependencyContext` and | ||
* `useDependencyContextValue` instead. | ||
* @deprecated Please use `useObservable` instead. | ||
*/ | ||
@@ -28,3 +37,56 @@ export function useDependencyValue(depValue$, defaultValue) { | ||
} | ||
function unwrap(o) { | ||
if (typeof o === 'function') { | ||
return o(); | ||
} | ||
return o; | ||
} | ||
/** | ||
* Subscribe to an observable and return its value. The component will re-render when the observable emits a new value. | ||
* | ||
* @param observable An observable or a function that returns an observable | ||
* @param defaultValue The default value of the observable. It the `observable` can omit an initial value, this value will be neglected. | ||
* @param shouldHaveSyncValue If the observable should have a sync value. If it does not have a sync value, an error will be thrown. | ||
* @param deps A dependency array to decide if we should re-subscribe when the `observable` is a function. | ||
* @returns | ||
*/ | ||
export function useObservable(observable, defaultValue, shouldHaveSyncValue, deps) { | ||
if (typeof observable === 'function' && !deps) { | ||
throw new RediError("Expected deps to be provided when observable is a function!"); | ||
} | ||
var observableRef = useRef(null); | ||
var initializedRef = useRef(false); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
var destObservable = useMemo(function () { return observable; }, __spreadArray([], (typeof deps !== 'undefined' ? deps : [observable]), true)); | ||
// This state is only for trigger React to re-render. We do not use `setValue` directly because it may cause | ||
// memory leaking. | ||
var _a = useState(0), _ = _a[0], setRenderCounter = _a[1]; | ||
var valueRef = useRef((function () { | ||
var innerDefaultValue; | ||
if (destObservable) { | ||
var sub = unwrap(destObservable).subscribe(function (value) { | ||
initializedRef.current = true; | ||
innerDefaultValue = value; | ||
}); | ||
sub.unsubscribe(); | ||
} | ||
return innerDefaultValue !== null && innerDefaultValue !== void 0 ? innerDefaultValue : defaultValue; | ||
})()); | ||
useEffect(function () { | ||
var subscription = null; | ||
if (destObservable) { | ||
observableRef.current = unwrap(destObservable); | ||
subscription = observableRef.current.subscribe(function (value) { | ||
valueRef.current = value; | ||
setRenderCounter(function (prev) { return prev + 1; }); | ||
}); | ||
} | ||
return function () { return subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe(); }; | ||
}, [destObservable]); | ||
if (shouldHaveSyncValue && !initializedRef.current) { | ||
throw new Error('Expect `shouldHaveSyncValue` but not getting a sync value!'); | ||
} | ||
return valueRef.current; | ||
} | ||
/** | ||
* subscribe to a signal that emits whenever data updates and re-render | ||
@@ -31,0 +93,0 @@ * |
@@ -147,2 +147,11 @@ import * as React from 'react'; | ||
var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
/** | ||
@@ -152,9 +161,9 @@ * unwrap an observable value, return it to the component for rendering, and | ||
* | ||
* **IMPORTANT**. Parent and child components should not subscribe to the same | ||
* **IMPORTANT**. Parent and child components better not subscribe to the same | ||
* observable, otherwise unnecessary re-render would be triggered. Instead, the | ||
* top-most component should subscribe and pass value of the observable to | ||
* its offspring, by props or context. | ||
* its offspring, by props or context. Please consider using `useDependencyContext` and | ||
* `useDependencyContextValue` in this case. | ||
* | ||
* If you have to do that, consider using `useDependencyContext` and | ||
* `useDependencyContextValue` instead. | ||
* @deprecated Please use `useObservable` instead. | ||
*/ | ||
@@ -172,3 +181,56 @@ function useDependencyValue(depValue$, defaultValue) { | ||
} | ||
function unwrap(o) { | ||
if (typeof o === 'function') { | ||
return o(); | ||
} | ||
return o; | ||
} | ||
/** | ||
* Subscribe to an observable and return its value. The component will re-render when the observable emits a new value. | ||
* | ||
* @param observable An observable or a function that returns an observable | ||
* @param defaultValue The default value of the observable. It the `observable` can omit an initial value, this value will be neglected. | ||
* @param shouldHaveSyncValue If the observable should have a sync value. If it does not have a sync value, an error will be thrown. | ||
* @param deps A dependency array to decide if we should re-subscribe when the `observable` is a function. | ||
* @returns | ||
*/ | ||
function useObservable(observable, defaultValue, shouldHaveSyncValue, deps) { | ||
if (typeof observable === 'function' && !deps) { | ||
throw new RediError("Expected deps to be provided when observable is a function!"); | ||
} | ||
var observableRef = useRef(null); | ||
var initializedRef = useRef(false); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
var destObservable = useMemo(function () { return observable; }, __spreadArray([], (typeof deps !== 'undefined' ? deps : [observable]), true)); | ||
// This state is only for trigger React to re-render. We do not use `setValue` directly because it may cause | ||
// memory leaking. | ||
var _a = useState(0), _ = _a[0], setRenderCounter = _a[1]; | ||
var valueRef = useRef((function () { | ||
var innerDefaultValue; | ||
if (destObservable) { | ||
var sub = unwrap(destObservable).subscribe(function (value) { | ||
initializedRef.current = true; | ||
innerDefaultValue = value; | ||
}); | ||
sub.unsubscribe(); | ||
} | ||
return innerDefaultValue !== null && innerDefaultValue !== void 0 ? innerDefaultValue : defaultValue; | ||
})()); | ||
useEffect(function () { | ||
var subscription = null; | ||
if (destObservable) { | ||
observableRef.current = unwrap(destObservable); | ||
subscription = observableRef.current.subscribe(function (value) { | ||
valueRef.current = value; | ||
setRenderCounter(function (prev) { return prev + 1; }); | ||
}); | ||
} | ||
return function () { return subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe(); }; | ||
}, [destObservable]); | ||
if (shouldHaveSyncValue && !initializedRef.current) { | ||
throw new Error('Expect `shouldHaveSyncValue` but not getting a sync value!'); | ||
} | ||
return valueRef.current; | ||
} | ||
/** | ||
* subscribe to a signal that emits whenever data updates and re-render | ||
@@ -219,3 +281,3 @@ * | ||
export { RediConsumer, RediContext, RediProvider, WithDependency, connectDependencies, connectInjector, useDependency, useDependencyContext, useDependencyContextValue, useDependencyValue, useInjector, useUpdateBinder }; | ||
export { RediConsumer, RediContext, RediProvider, WithDependency, connectDependencies, connectInjector, useDependency, useDependencyContext, useDependencyContextValue, useDependencyValue, useInjector, useObservable, useUpdateBinder }; | ||
//# sourceMappingURL=react-bindings.js.map |
{ | ||
"$schema": "https://raw.githubusercontent.com/wzhudev/squirrel/master/src/schema/package.schema.json", | ||
"name": "@wendellhu/redi", | ||
"version": "0.14.0", | ||
"version": "0.15.0", | ||
"description": "A dependency library for TypeScript and JavaScript, along with a binding for React.", | ||
@@ -6,0 +6,0 @@ "author": "Wenzhao Hu<wzhudev@gmail.com>", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
494604
5002