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

react-updater

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-updater - npm Package Compare versions

Comparing version 1.0.3 to 1.1.0

es/utils.js

228

dist/react-updater.js

@@ -9,2 +9,16 @@ (function (global, factory) {

var stringifyFunction = function stringifyFunction(fn) {
return '[Function ' + fn.name + ']';
};
var noop = function noop() {};
var stringify = function stringify(value) {
return JSON.stringify(value, function (key, value) {
if (typeof value === 'function') {
return stringifyFunction(value);
}
return value;
});
};
/*!

@@ -50,6 +64,6 @@ * isobject <https://github.com/jonschlinkert/isobject>

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -70,3 +84,2 @@

var STATE_PROPERTY_NAME = '@@STATE';
var MAX_CALLBACKS_COUNT = 30;

@@ -77,146 +90,131 @@ /**

var index = (function () {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var index = (function (initialState) {
return function (WrappedComponent) {
return function (_Component) {
_inherits(EnhancedComponent, _Component);
var WithUpdater = function (_Component) {
_inherits(WithUpdater, _Component);
function EnhancedComponent(props) {
_classCallCheck(this, EnhancedComponent);
function WithUpdater(props) {
_classCallCheck(this, WithUpdater);
var _this = _possibleConstructorReturn(this, (EnhancedComponent.__proto__ || Object.getPrototypeOf(EnhancedComponent)).call(this, props));
var _this = _possibleConstructorReturn(this, (WithUpdater.__proto__ || Object.getPrototypeOf(WithUpdater)).call(this, props));
_this.cachedUpdateCount = 0;
_this.cachedHandleCount = 0;
_this.handleCallbacksRefs = new WeakMap();
_this.updateCallbacksRefs = new WeakMap();
_initialiseProps.call(_this);
_this.handle = function (fn) {
for (var _len = arguments.length, values = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
values[_key - 1] = arguments[_key];
}
var state = typeof initialState === 'function' ? initialState(props) : initialState;
if (!_this.handleCallbacksRefs.has(fn)) {
if ("development" !== 'production' && _this.cachedHandleCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "handle" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
_this.state = index$1(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
return _this;
}
var handler = function handler() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
_createClass(WithUpdater, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.memoizedCallbackHandlers = null;
}
return fn.apply(undefined, _toConsumableArray(handler.values).concat(args));
};
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
*/
handler.values = values;
_this.handleCallbacksRefs.set(fn, handler);
_this.cachedHandleCount++;
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
*/
return handler;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
var cached = _this.handleCallbacksRefs.get(fn);
return React__default.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
cached.values = values;
return WithUpdater;
}(React.Component);
return cached;
};
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
_this.update = function (fn) {
for (var _len3 = arguments.length, values = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
values[_key3 - 1] = arguments[_key3];
this.memoizedCallbackHandlers = {};
this.createCallbackHandler = function (name, createHandler) {
return function (callback) {
for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
params[_key - 1] = arguments[_key];
}
if (!_this.updateCallbacksRefs.has(fn)) {
if ("development" !== 'production' && _this.cachedUpdateCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "update" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
if ("development" !== 'production' && !callback.name) {
// eslint-disable-next-line no-console
console.warning('Callbacks handlers defined with anonymous functions should be' + ' avoided. This can lead to de-optimisations on components' + ' that rely on props equality.');
var updater = function updater() {
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
return noop;
}
var values = updater.values;
var id = name + stringifyFunction(callback) + stringify(params);
if (!_this2.memoizedCallbackHandlers[id]) {
var handler = createHandler(callback, params);
_this.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return fn.apply(undefined, [state].concat(_toConsumableArray(values), args));
}
_this2.memoizedCallbackHandlers[id] = { callback: callback, handler: handler };
return _defineProperty({}, STATE_PROPERTY_NAME, fn.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(values), args)));
});
return handler;
}
// We need to ensure the handler is updated for different callbacks.
// Since we check for the callback.name property, if another callback
// with the same `name` were passed, the returned handler would the
// call the previous callback.
if (_this2.memoizedCallbackHandlers[id].callback !== callback) {
_this2.memoizedCallbackHandlers[id] = {
callback: callback,
handler: createHandler(callback, params)
};
}
updater.values = values;
_this.updateCallbacksRefs.set(fn, updater);
_this.cachedUpdateCount++;
return _this2.memoizedCallbackHandlers[id].handler;
};
};
return updater;
this.handle = this.createCallbackHandler('handle', function (callback, params) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var cached = _this.updateCallbacksRefs.get(fn);
return callback.apply(undefined, _toConsumableArray(params).concat(args));
};
});
this.update = this.createCallbackHandler('update', function (callback, params) {
return function () {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
cached.values = values;
_this2.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return callback.apply(undefined, [state].concat(_toConsumableArray(params), args));
}
return cached;
return _defineProperty({}, STATE_PROPERTY_NAME, callback.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(params), args)));
});
};
});
};
if (typeof initialState === 'function') {
var state = initialState(props);
{
var wrappedComponentDisplayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
_this.state = index$1(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
} else {
_this.state = index$1(initialState) ? initialState : _defineProperty({}, STATE_PROPERTY_NAME, initialState);
}
return _this;
}
WithUpdater.displayName = 'withUpdater(' + wrappedComponentDisplayName + ')';
}
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
_createClass(EnhancedComponent, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cachedHandleCount = null;
this.cachedUpdateCount = null;
this.handleCallbacksRefs = null;
this.updateCallbacksRefs = null;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
return React__default.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
return EnhancedComponent;
}(React.Component);
return WithUpdater;
};

@@ -223,0 +221,0 @@ });

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

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):e.withUpdater=t(e.React)}(this,function(e){"use strict";function t(e){return!0===c(e)&&"[object Object]"===Object.prototype.toString.call(e)}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);e.length>t;t++)n[t]=e[t];return n}return Array.from(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function u(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var l="default"in e?e.default:e,c=function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)},i=function(e){var n,r;return!1!==t(e)&&("function"==typeof(n=e.constructor)&&(r=n.prototype,!1!==t(r)&&!1!==r.hasOwnProperty("isPrototypeOf")))},f=function(){function e(e,t){for(var n=0;t.length>n;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),s="@@STATE";return function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return function(c){return function(e){function p(e){a(this,p);var u=o(this,(p.__proto__||Object.getPrototypeOf(p)).call(this,e));if(u.cachedUpdateCount=0,u.cachedHandleCount=0,u.handleCallbacksRefs=new WeakMap,u.updateCallbacksRefs=new WeakMap,u.handle=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),a=1;t>a;a++)n[a-1]=arguments[a];if(!u.handleCallbacksRefs.has(e)){var o=function t(){for(var n=arguments.length,a=Array(n),o=0;n>o;o++)a[o]=arguments[o];return e.apply(void 0,r(t.values).concat(a))};return o.values=n,u.handleCallbacksRefs.set(e,o),u.cachedHandleCount++,o}var l=u.handleCallbacksRefs.get(e);return l.values=n,l},u.update=function(e){for(var t=arguments.length,a=Array(t>1?t-1:0),o=1;t>o;o++)a[o-1]=arguments[o];if(!u.updateCallbacksRefs.has(e)){var l=function t(){for(var a=arguments.length,o=Array(a),l=0;a>l;l++)o[l]=arguments[l];var c=t.values;u.setState(function(t){return void 0===t[s]?e.apply(void 0,[t].concat(r(c),o)):n({},s,e.apply(void 0,[t[s]].concat(r(c),o)))})};return l.values=a,u.updateCallbacksRefs.set(e,l),u.cachedUpdateCount++,l}var c=u.updateCallbacksRefs.get(e);return c.values=a,c},"function"==typeof t){var l=t(e);u.state=i(l)?l:n({},s,l)}else u.state=i(t)?t:n({},s,t);return u}return u(p,e),f(p,[{key:"componentWillUnmount",value:function(){this.cachedHandleCount=null,this.cachedUpdateCount=null,this.handleCallbacksRefs=null,this.updateCallbacksRefs=null}},{key:"render",value:function(){var e=void 0===this.state[s]?this.state:this.state[s];return l.createElement(c,Object.assign({},this.props,{handle:this.handle,state:e,update:this.update}))}}]),p}(e.Component)}}});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):e.withUpdater=t(e.React)}(this,function(e){"use strict";function t(e){return!0===f(e)&&"[object Object]"===Object.prototype.toString.call(e)}function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);e.length>t;t++)n[t]=e[t];return n}return Array.from(e)}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var c="default"in e?e.default:e,u=function(e){return"[Function "+e.name+"]"},l=function(e){return JSON.stringify(e,function(e,t){return"function"==typeof t?u(t):t})},f=function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)},s=function(e){var n,r;return!1!==t(e)&&("function"==typeof(n=e.constructor)&&(r=n.prototype,!1!==t(r)&&!1!==r.hasOwnProperty("isPrototypeOf")))},p=function(){function e(e,t){for(var n=0;t.length>n;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),d="@@STATE";return function(t){return function(f){var y=function(e){function n(e){o(this,n);var i=a(this,(n.__proto__||Object.getPrototypeOf(n)).call(this,e));h.call(i);var c="function"==typeof t?t(e):t;return i.state=s(c)?c:r({},d,c),i}return i(n,e),p(n,[{key:"componentWillUnmount",value:function(){this.memoizedCallbackHandlers=null}},{key:"render",value:function(){var e=void 0===this.state[d]?this.state:this.state[d];return c.createElement(f,Object.assign({},this.props,{handle:this.handle,state:e,update:this.update}))}}]),n}(e.Component),h=function(){var e=this;this.memoizedCallbackHandlers={},this.createCallbackHandler=function(t,n){return function(r){for(var o=arguments.length,a=Array(o>1?o-1:0),i=1;o>i;i++)a[i-1]=arguments[i];var c=t+u(r)+l(a);if(!e.memoizedCallbackHandlers[c]){var f=n(r,a);return e.memoizedCallbackHandlers[c]={callback:r,handler:f},f}return e.memoizedCallbackHandlers[c].callback!==r&&(e.memoizedCallbackHandlers[c]={callback:r,handler:n(r,a)}),e.memoizedCallbackHandlers[c].handler}},this.handle=this.createCallbackHandler("handle",function(e,t){return function(){for(var r=arguments.length,o=Array(r),a=0;r>a;a++)o[a]=arguments[a];return e.apply(void 0,n(t).concat(o))}}),this.update=this.createCallbackHandler("update",function(t,o){return function(){for(var a=arguments.length,i=Array(a),c=0;a>c;c++)i[c]=arguments[c];e.setState(function(e){return void 0===e[d]?t.apply(void 0,[e].concat(n(o),i)):r({},d,t.apply(void 0,[e[d]].concat(n(o),i)))})}})};return y}}});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -18,2 +18,3 @@

import React, { Component } from 'react';
import { noop, stringify, stringifyFunction } from './utils';
import isPlainObject from 'is-plain-object';

@@ -26,3 +27,2 @@

var STATE_PROPERTY_NAME = '@@STATE';
var MAX_CALLBACKS_COUNT = 30;

@@ -33,147 +33,132 @@ /**

export default (function () {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
export default (function (initialState) {
return function (WrappedComponent) {
return function (_Component) {
_inherits(EnhancedComponent, _Component);
var WithUpdater = function (_Component) {
_inherits(WithUpdater, _Component);
function EnhancedComponent(props) {
_classCallCheck(this, EnhancedComponent);
function WithUpdater(props) {
_classCallCheck(this, WithUpdater);
var _this = _possibleConstructorReturn(this, (EnhancedComponent.__proto__ || Object.getPrototypeOf(EnhancedComponent)).call(this, props));
var _this = _possibleConstructorReturn(this, (WithUpdater.__proto__ || Object.getPrototypeOf(WithUpdater)).call(this, props));
_this.cachedUpdateCount = 0;
_this.cachedHandleCount = 0;
_this.handleCallbacksRefs = new WeakMap();
_this.updateCallbacksRefs = new WeakMap();
_initialiseProps.call(_this);
_this.handle = function (fn) {
for (var _len = arguments.length, values = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
values[_key - 1] = arguments[_key];
}
var state = typeof initialState === 'function' ? initialState(props) : initialState;
if (!_this.handleCallbacksRefs.has(fn)) {
if (process.env.NODE_ENV !== 'production' && _this.cachedHandleCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "handle" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
_this.state = isPlainObject(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
return _this;
}
var handler = function handler() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
_createClass(WithUpdater, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.memoizedCallbackHandlers = null;
}
return fn.apply(undefined, _toConsumableArray(handler.values).concat(args));
};
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
*/
handler.values = values;
_this.handleCallbacksRefs.set(fn, handler);
_this.cachedHandleCount++;
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
*/
return handler;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
var cached = _this.handleCallbacksRefs.get(fn);
return React.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
cached.values = values;
return WithUpdater;
}(Component);
return cached;
};
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
_this.update = function (fn) {
for (var _len3 = arguments.length, values = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
values[_key3 - 1] = arguments[_key3];
this.memoizedCallbackHandlers = {};
this.createCallbackHandler = function (name, createHandler) {
return function (callback) {
for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
params[_key - 1] = arguments[_key];
}
if (!_this.updateCallbacksRefs.has(fn)) {
if (process.env.NODE_ENV !== 'production' && _this.cachedUpdateCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "update" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
if (process.env.NODE_ENV !== 'production' && !callback.name) {
// eslint-disable-next-line no-console
console.warning('Callbacks handlers defined with anonymous functions should be' + ' avoided. This can lead to de-optimisations on components' + ' that rely on props equality.');
var updater = function updater() {
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
return noop;
}
var values = updater.values;
var id = name + stringifyFunction(callback) + stringify(params);
if (!_this2.memoizedCallbackHandlers[id]) {
var handler = createHandler(callback, params);
_this.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return fn.apply(undefined, [state].concat(_toConsumableArray(values), args));
}
_this2.memoizedCallbackHandlers[id] = { callback: callback, handler: handler };
return _defineProperty({}, STATE_PROPERTY_NAME, fn.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(values), args)));
});
return handler;
}
// We need to ensure the handler is updated for different callbacks.
// Since we check for the callback.name property, if another callback
// with the same `name` were passed, the returned handler would the
// call the previous callback.
if (_this2.memoizedCallbackHandlers[id].callback !== callback) {
_this2.memoizedCallbackHandlers[id] = {
callback: callback,
handler: createHandler(callback, params)
};
}
updater.values = values;
_this.updateCallbacksRefs.set(fn, updater);
_this.cachedUpdateCount++;
return _this2.memoizedCallbackHandlers[id].handler;
};
};
return updater;
this.handle = this.createCallbackHandler('handle', function (callback, params) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var cached = _this.updateCallbacksRefs.get(fn);
return callback.apply(undefined, _toConsumableArray(params).concat(args));
};
});
this.update = this.createCallbackHandler('update', function (callback, params) {
return function () {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
cached.values = values;
_this2.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return callback.apply(undefined, [state].concat(_toConsumableArray(params), args));
}
return cached;
return _defineProperty({}, STATE_PROPERTY_NAME, callback.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(params), args)));
});
};
});
};
if (typeof initialState === 'function') {
var state = initialState(props);
if (process.env.NODE_ENV !== 'production') {
var wrappedComponentDisplayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
_this.state = isPlainObject(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
} else {
_this.state = isPlainObject(initialState) ? initialState : _defineProperty({}, STATE_PROPERTY_NAME, initialState);
}
return _this;
}
WithUpdater.displayName = 'withUpdater(' + wrappedComponentDisplayName + ')';
}
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
_createClass(EnhancedComponent, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cachedHandleCount = null;
this.cachedUpdateCount = null;
this.handleCallbacksRefs = null;
this.updateCallbacksRefs = null;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
return React.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
return EnhancedComponent;
}(Component);
return WithUpdater;
};
});

@@ -13,2 +13,4 @@ 'use strict';

var _utils = require('./utils');
var _isPlainObject = require('is-plain-object');

@@ -20,6 +22,6 @@

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -38,3 +40,2 @@

var STATE_PROPERTY_NAME = '@@STATE';
var MAX_CALLBACKS_COUNT = 30;

@@ -45,147 +46,132 @@ /**

exports.default = function () {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
exports.default = function (initialState) {
return function (WrappedComponent) {
return function (_Component) {
_inherits(EnhancedComponent, _Component);
var WithUpdater = function (_Component) {
_inherits(WithUpdater, _Component);
function EnhancedComponent(props) {
_classCallCheck(this, EnhancedComponent);
function WithUpdater(props) {
_classCallCheck(this, WithUpdater);
var _this = _possibleConstructorReturn(this, (EnhancedComponent.__proto__ || Object.getPrototypeOf(EnhancedComponent)).call(this, props));
var _this = _possibleConstructorReturn(this, (WithUpdater.__proto__ || Object.getPrototypeOf(WithUpdater)).call(this, props));
_this.cachedUpdateCount = 0;
_this.cachedHandleCount = 0;
_this.handleCallbacksRefs = new WeakMap();
_this.updateCallbacksRefs = new WeakMap();
_initialiseProps.call(_this);
_this.handle = function (fn) {
for (var _len = arguments.length, values = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
values[_key - 1] = arguments[_key];
}
var state = typeof initialState === 'function' ? initialState(props) : initialState;
if (!_this.handleCallbacksRefs.has(fn)) {
if (process.env.NODE_ENV !== 'production' && _this.cachedHandleCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "handle" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
_this.state = (0, _isPlainObject2.default)(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
return _this;
}
var handler = function handler() {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
_createClass(WithUpdater, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.memoizedCallbackHandlers = null;
}
return fn.apply(undefined, _toConsumableArray(handler.values).concat(args));
};
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
*/
handler.values = values;
_this.handleCallbacksRefs.set(fn, handler);
_this.cachedHandleCount++;
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
*/
return handler;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
var cached = _this.handleCallbacksRefs.get(fn);
return _react2.default.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
cached.values = values;
return WithUpdater;
}(_react.Component);
return cached;
};
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
_this.update = function (fn) {
for (var _len3 = arguments.length, values = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
values[_key3 - 1] = arguments[_key3];
this.memoizedCallbackHandlers = {};
this.createCallbackHandler = function (name, createHandler) {
return function (callback) {
for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
params[_key - 1] = arguments[_key];
}
if (!_this.updateCallbacksRefs.has(fn)) {
if (process.env.NODE_ENV !== 'production' && _this.cachedUpdateCount === MAX_CALLBACKS_COUNT) {
// eslint-disable-next-line no-console
console.error('Maximum "update" callbacks size exceeded. This probably is because' + ' you are creating inline handlers inside the render method,' + ' which results in a new handler on every render which can lead' + ' to de-optimizations by components that rely on props equality.');
}
if (process.env.NODE_ENV !== 'production' && !callback.name) {
// eslint-disable-next-line no-console
console.warning('Callbacks handlers defined with anonymous functions should be' + ' avoided. This can lead to de-optimisations on components' + ' that rely on props equality.');
var updater = function updater() {
for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
return _utils.noop;
}
var values = updater.values;
var id = name + (0, _utils.stringifyFunction)(callback) + (0, _utils.stringify)(params);
if (!_this2.memoizedCallbackHandlers[id]) {
var handler = createHandler(callback, params);
_this.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return fn.apply(undefined, [state].concat(_toConsumableArray(values), args));
}
_this2.memoizedCallbackHandlers[id] = { callback: callback, handler: handler };
return _defineProperty({}, STATE_PROPERTY_NAME, fn.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(values), args)));
});
return handler;
}
// We need to ensure the handler is updated for different callbacks.
// Since we check for the callback.name property, if another callback
// with the same `name` were passed, the returned handler would the
// call the previous callback.
if (_this2.memoizedCallbackHandlers[id].callback !== callback) {
_this2.memoizedCallbackHandlers[id] = {
callback: callback,
handler: createHandler(callback, params)
};
}
updater.values = values;
_this.updateCallbacksRefs.set(fn, updater);
_this.cachedUpdateCount++;
return _this2.memoizedCallbackHandlers[id].handler;
};
};
return updater;
this.handle = this.createCallbackHandler('handle', function (callback, params) {
return function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var cached = _this.updateCallbacksRefs.get(fn);
return callback.apply(undefined, _toConsumableArray(params).concat(args));
};
});
this.update = this.createCallbackHandler('update', function (callback, params) {
return function () {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
cached.values = values;
_this2.setState(function (state) {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return callback.apply(undefined, [state].concat(_toConsumableArray(params), args));
}
return cached;
return _defineProperty({}, STATE_PROPERTY_NAME, callback.apply(undefined, [state[STATE_PROPERTY_NAME]].concat(_toConsumableArray(params), args)));
});
};
});
};
if (typeof initialState === 'function') {
var state = initialState(props);
if (process.env.NODE_ENV !== 'production') {
var wrappedComponentDisplayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
_this.state = (0, _isPlainObject2.default)(state) ? state : _defineProperty({}, STATE_PROPERTY_NAME, state);
} else {
_this.state = (0, _isPlainObject2.default)(initialState) ? initialState : _defineProperty({}, STATE_PROPERTY_NAME, initialState);
}
return _this;
}
WithUpdater.displayName = 'withUpdater(' + wrappedComponentDisplayName + ')';
}
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
/**
* Wraps the callback handler in a `setState` call and returns a new
* function that receives the previous state and the given arguments.
* Since this wraps the callback handler in a `setState` call, the handler
* should always return a new state which can be an object or a single
* value.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
_createClass(EnhancedComponent, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cachedHandleCount = null;
this.cachedUpdateCount = null;
this.handleCallbacksRefs = null;
this.updateCallbacksRefs = null;
}
}, {
key: 'render',
value: function render() {
var state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined' ? this.state : this.state[STATE_PROPERTY_NAME];
return _react2.default.createElement(WrappedComponent, Object.assign({}, this.props, {
handle: this.handle,
state: state,
update: this.update
}));
}
}]);
return EnhancedComponent;
}(_react.Component);
return WithUpdater;
};
};
{
"name": "react-updater",
"description": "Functional stateful components made easy",
"version": "1.0.3",
"version": "1.1.0",
"browser": "dist/react-updater.js",

@@ -6,0 +6,0 @@ "main": "lib/index.js",

@@ -22,2 +22,39 @@ # React Updater

## How It Works
React functional components are stateless so we need to use classes if we want to have local state. A simple solution to this is to delegate the state to an ancestor by creating an Higher-order Component to wrap the stateless component into a stateful component. The problem here is that if we return a new callback handler on subsequent renders we cannot guarantee reference equality, which can be a problem for components that rely on `props` equality.
By memoizing state updaters and additional parameters, React Updater guarantees the referential equality of the callback handlers across renders.
It also requires you to pass a function as state updater. This has some benefits: it ensures the state is always predictable across multiple calls of `setState()` and you can unit test complex state transitions without shallow render.
Since in functional components you cannot access `this`, it provides you a way to attach `props` and other data to your state updaters without using closures.
To create a stateful functional component you just need to define the initial state, specify your state updaters and pass them to the `update()` function. That's it!
```js
import React from 'react';
import ReactDOM from 'react-dom';
import withUpdater from 'react-updater';
// Initial state.
const state = 0;
// State updaters.
const increment = (state, props, event) => state + props.step;
const decrement = (state, props, event) => state - props.step;
const Counter = (props) => (
<div>
<h1>{props.state}</h1>
<button onClick={props.update(decrement, props)}>{'-'}</button>
<button onClick={props.update(increment, props)}>{'+'}</button>
</div>
);
const App = withUpdater(state)(Counter);
ReactDOM.render(<App step={1} />, document.getElementById('root'));
```
## API

@@ -38,9 +75,7 @@

```js
update(handler: Function, ...args): (...args): void
update(handler: Function, ...params): (...args): void
```
This function wraps every callback handler. It takes a callback and returns a new `memoized` callback that will give you the previous state, and additional arguments when the callback is called and ensures the state is updated after the callback.
This function wraps every callback handler. It takes a callback and returns a **memoized** callback that will give you the previous state, and additional arguments when the callback is called and ensures the state is updated after the callback.
**Example:**
```js

@@ -55,7 +90,7 @@ const onClick = (state, increment) => state + increment;

**Important:** `update` memoizes up to **30** handlers and returns the same reference. This avoids a common pitfall associated with components that rely on props equality by using `shouldComponentUpdate` which can lead to de-optimizations because `shouldComponentUpdate` will return `true` every time since `props.onClick !== nexProps.onClick`. This way `withUpdater` must ensure it always returns the same reference for each handler.
**Important:** `update` memoizes the given state updaters in order to avoid a common pitfall associated with components that rely on props equality by using `shouldComponentUpdate`. Using classes this is avoided by using `this.onClick`, but if you pass inline functions as a state updater, `update()` will return a new callback handler. This can lead to de-optimizations because `shouldComponentUpdate` will return `true` on every render since `props.onClick !== nexProps.onClick`. This way we can ensure it will always returns the same reference for each handler.
```js
// Bad.
// This will log a error message after 30 calls.
// This will log a warning message since the given handler is a anonymous function.
const Component = props => <div onClick={props.update(state => state + 1)} />;

@@ -73,6 +108,6 @@

```js
handle(handler: Function, ...args): (...args): Function
handle(handler: Function, ...params): (...args): Function
```
This method is a convenient subset of `update()` but it does not update the state, so there is no need to return a new `state`.
This method is a convenient subset of `update()` but it does not update the state, so there is no need to return a new `state`. This allows passing `props` or other data to events without needing to use closures, while keeping the function referential identity.

@@ -95,3 +130,3 @@ **Example:**

#### `state`
The main difference here is that you can pass any value to the initial state and it will be handled accordingly. If you pass an object as the initial state, the updater will handle it according to the default `setState()` behavior. If you pass a function to the initial state it will be provided with the owner props that can be used to define the initial state.
You can pass any arbitrary value to the initial state and it will be handled accordingly. If you pass an object as the initial state, the updater will handle it according to the default `setState()` behavior. If you pass a function to the initial state it will be provided with the owner props that can be used to define the initial state.

@@ -162,4 +197,4 @@ **Arbitrary value**

```js
const count = (state = 0, action = {}) => {
switch (action.type) {
const count = (state = 0, action) => {
switch (action) {
case 'DECREMENT':

@@ -178,7 +213,7 @@ return state - 1;

<button onClick={props.update(count, { type: 'DECREMENT' })}>
<button onClick={props.update(count, 'DECREMENT')}>
{'-'}
</button>
<button onClick={props.update(count, { type: 'INCREMENT' })}>
<button onClick={props.update(count, 'INCREMENT')}>
{'+'}

@@ -192,46 +227,7 @@ </button>

You can even use [recompose withHandlers](https://github.com/acdlite/recompose/blob/master/docs/API.md#withhandlers) util to map the `props.update(count, { type })` to different methods. Considering the example above:
```js
const count = (state = 0, action = {}) => {
switch (action.type) {
case 'DECREMENT':
return state - 1;
case 'INCREMENT':
return state + 1;
default:
return state;
}
};
const Counter = props => (
<div>
<div>{props.state}</div>
<button onClick={props.decrement}>
{'-'}
</button>
<button onClick={props.increment}>
{'+'}
</button>
</div>
);
export default compose(
withUpdater(count())
withHandlers({
decrement: props => props.update(count, { type: DECREMENT }),
increment: props => props.update(count, { type: INCREMENT })
})
)(Counter);
```
## References
This library takes some cues from to the [Reason-React](https://github.com/reasonml/reason-react) implementation of the state updater.
- [Reason-React](https://github.com/reasonml/reason-react)
- [Recompose](https://github.com/acdlite/recompose)
## Licence
MIT © [João Granado](https://github.com/joaogranado)

@@ -6,2 +6,3 @@ /**

import React, { Component } from 'react';
import { noop, stringify, stringifyFunction } from './utils';
import isPlainObject from 'is-plain-object';

@@ -14,3 +15,2 @@

const STATE_PROPERTY_NAME = '@@STATE';
const MAX_CALLBACKS_COUNT = 30;

@@ -21,9 +21,6 @@ /**

export default (initialState = null) => {
export default initialState => {
return WrappedComponent => {
return class EnhancedComponent extends Component {
cachedUpdateCount = 0;
cachedHandleCount = 0;
handleCallbacksRefs = new WeakMap();
updateCallbacksRefs = new WeakMap();
class WithUpdater extends Component {
memoizedCallbackHandlers = {};

@@ -33,55 +30,63 @@ constructor(props) {

if (typeof initialState === 'function') {
const state = initialState(props);
const state = typeof initialState === 'function'
? initialState(props)
: initialState;
this.state = isPlainObject(state)
? state
: { [STATE_PROPERTY_NAME]: state };
} else {
this.state = isPlainObject(initialState)
? initialState
: { [STATE_PROPERTY_NAME]: initialState };
}
this.state = isPlainObject(state)
? state
: { [STATE_PROPERTY_NAME]: state };
}
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
componentWillUnmount() {
this.memoizedCallbackHandlers = null;
}
handle = (fn, ...values) => {
if (!this.handleCallbacksRefs.has(fn)) {
if (
process.env.NODE_ENV !== 'production' &&
this.cachedHandleCount === MAX_CALLBACKS_COUNT
) {
createCallbackHandler = (name, createHandler) => {
return (callback, ...params) => {
if (process.env.NODE_ENV !== 'production' && !callback.name) {
// eslint-disable-next-line no-console
console.error(
'Maximum "handle" callbacks size exceeded. This probably is because' +
' you are creating inline handlers inside the render method,' +
' which results in a new handler on every render which can lead' +
' to de-optimizations by components that rely on props equality.'
console.warning(
'Callbacks handlers defined with anonymous functions should be' +
' avoided. This can lead to de-optimisations on components' +
' that rely on props equality.'
);
return noop;
}
const handler = (...args) => fn(...handler.values, ...args);
const id = name + stringifyFunction(callback) + stringify(params);
handler.values = values;
this.handleCallbacksRefs.set(fn, handler);
this.cachedHandleCount++;
if (!this.memoizedCallbackHandlers[id]) {
const handler = createHandler(callback, params);
return handler;
}
this.memoizedCallbackHandlers[id] = { callback, handler };
const cached = this.handleCallbacksRefs.get(fn);
return handler;
}
cached.values = values;
// We need to ensure the handler is updated for different callbacks.
// Since we check for the callback.name property, if another callback
// with the same `name` were passed, the returned handler would the
// call the previous callback.
if (this.memoizedCallbackHandlers[id].callback !== callback) {
this.memoizedCallbackHandlers[id] = {
callback,
handler: createHandler(callback, params)
};
}
return cached;
return this.memoizedCallbackHandlers[id].handler;
};
};
/**
* Wraps the callback handler and returns a new function that receives
* additional arguments.
*/
handle = this.createCallbackHandler('handle', (callback, params) => {
return (...args) => callback(...params, ...args);
});
/**
* Wraps the callback handler in a `setState` call and returns a new

@@ -92,61 +97,22 @@ * function that receives the previous state and the given arguments.

* value.
* This method memoizes up to **30** handlers in order to avoid a common
* pitfall associated with components that rely on props equality
* (e.g:. `shouldComponentUpdate`) which can lead to de-optimizations.
*/
update = (fn, ...values) => {
if (!this.updateCallbacksRefs.has(fn)) {
if (
process.env.NODE_ENV !== 'production' &&
this.cachedUpdateCount === MAX_CALLBACKS_COUNT
) {
// eslint-disable-next-line no-console
console.error(
'Maximum "update" callbacks size exceeded. This probably is because' +
' you are creating inline handlers inside the render method,' +
' which results in a new handler on every render which can lead' +
' to de-optimizations by components that rely on props equality.'
);
}
update = this.createCallbackHandler('update', (callback, params) => {
return (...args) => {
this.setState(state => {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return callback(state, ...params, ...args);
}
const updater = (...args) => {
const { values } = updater;
return {
[STATE_PROPERTY_NAME]: callback(
state[STATE_PROPERTY_NAME],
...params,
...args
)
};
});
};
});
this.setState(state => {
if (typeof state[STATE_PROPERTY_NAME] === 'undefined') {
return fn(state, ...values, ...args);
}
return {
[STATE_PROPERTY_NAME]: fn(
state[STATE_PROPERTY_NAME],
...values,
...args
)
};
});
};
updater.values = values;
this.updateCallbacksRefs.set(fn, updater);
this.cachedUpdateCount++;
return updater;
}
const cached = this.updateCallbacksRefs.get(fn);
cached.values = values;
return cached;
};
componentWillUnmount() {
this.cachedHandleCount = null;
this.cachedUpdateCount = null;
this.handleCallbacksRefs = null;
this.updateCallbacksRefs = null;
}
render() {

@@ -166,4 +132,13 @@ const state = typeof this.state[STATE_PROPERTY_NAME] === 'undefined'

}
};
}
if (process.env.NODE_ENV !== 'production') {
const wrappedComponentDisplayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
WithUpdater.displayName = `withUpdater(${wrappedComponentDisplayName})`;
}
return WithUpdater;
};
};
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