react-proxy
Advanced tools
Comparing version
@@ -69,5 +69,5 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
var _getForceUpdate = __webpack_require__(15); | ||
var _reactDeepForceUpdate = __webpack_require__(39); | ||
exports.getForceUpdate = _interopRequire(_getForceUpdate); | ||
exports.getForceUpdate = _interopRequire(_reactDeepForceUpdate); | ||
@@ -112,3 +112,3 @@ /***/ }, | ||
var getLength = __webpack_require__(31), | ||
var getLength = __webpack_require__(30), | ||
isLength = __webpack_require__(5); | ||
@@ -152,3 +152,3 @@ | ||
var isNative = __webpack_require__(36); | ||
var isNative = __webpack_require__(35); | ||
@@ -384,3 +384,3 @@ /** | ||
isObject = __webpack_require__(1), | ||
shimKeys = __webpack_require__(34); | ||
shimKeys = __webpack_require__(33); | ||
@@ -632,7 +632,7 @@ /* Native method references for those with the same name as other `lodash` methods. */ | ||
var _lodashObjectAssign = __webpack_require__(37); | ||
var _lodashObjectAssign = __webpack_require__(36); | ||
var _lodashObjectAssign2 = _interopRequireDefault(_lodashObjectAssign); | ||
var _lodashArrayDifference = __webpack_require__(16); | ||
var _lodashArrayDifference = __webpack_require__(15); | ||
@@ -895,27 +895,4 @@ var _lodashArrayDifference2 = _interopRequireDefault(_lodashArrayDifference); | ||
/** | ||
* Returns a function that force-updates an instance | ||
* regardless of whether it descends from React.Component or not. | ||
*/ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports["default"] = getForceUpdate; | ||
function getForceUpdate(React) { | ||
return function (instance) { | ||
React.Component.prototype.forceUpdate.call(instance); | ||
}; | ||
} | ||
module.exports = exports["default"]; | ||
/***/ }, | ||
/* 16 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var baseDifference = __webpack_require__(22), | ||
baseFlatten = __webpack_require__(23), | ||
var baseDifference = __webpack_require__(21), | ||
baseFlatten = __webpack_require__(22), | ||
isArrayLike = __webpack_require__(2), | ||
@@ -951,6 +928,6 @@ isObjectLike = __webpack_require__(3), | ||
/***/ }, | ||
/* 17 */ | ||
/* 16 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/* WEBPACK VAR INJECTION */(function(global) {var cachePush = __webpack_require__(28), | ||
/* WEBPACK VAR INJECTION */(function(global) {var cachePush = __webpack_require__(27), | ||
getNative = __webpack_require__(4); | ||
@@ -988,3 +965,3 @@ | ||
/***/ }, | ||
/* 18 */ | ||
/* 17 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1015,3 +992,3 @@ | ||
/***/ }, | ||
/* 19 */ | ||
/* 18 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1054,6 +1031,6 @@ | ||
/***/ }, | ||
/* 20 */ | ||
/* 19 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var baseCopy = __webpack_require__(21), | ||
var baseCopy = __webpack_require__(20), | ||
keys = __webpack_require__(10); | ||
@@ -1080,3 +1057,3 @@ | ||
/***/ }, | ||
/* 21 */ | ||
/* 20 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1110,8 +1087,8 @@ | ||
/***/ }, | ||
/* 22 */ | ||
/* 21 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var baseIndexOf = __webpack_require__(24), | ||
cacheIndexOf = __webpack_require__(27), | ||
createCache = __webpack_require__(30); | ||
var baseIndexOf = __webpack_require__(23), | ||
cacheIndexOf = __webpack_require__(26), | ||
createCache = __webpack_require__(29); | ||
@@ -1172,6 +1149,6 @@ /** Used as the size to enable large array optimizations. */ | ||
/***/ }, | ||
/* 23 */ | ||
/* 22 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var arrayPush = __webpack_require__(18), | ||
var arrayPush = __webpack_require__(17), | ||
isArguments = __webpack_require__(7), | ||
@@ -1220,6 +1197,6 @@ isArray = __webpack_require__(8), | ||
/***/ }, | ||
/* 24 */ | ||
/* 23 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var indexOfNaN = __webpack_require__(32); | ||
var indexOfNaN = __webpack_require__(31); | ||
@@ -1254,3 +1231,3 @@ /** | ||
/***/ }, | ||
/* 25 */ | ||
/* 24 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1275,6 +1252,6 @@ | ||
/***/ }, | ||
/* 26 */ | ||
/* 25 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var identity = __webpack_require__(39); | ||
var identity = __webpack_require__(38); | ||
@@ -1321,3 +1298,3 @@ /** | ||
/***/ }, | ||
/* 27 */ | ||
/* 26 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1347,3 +1324,3 @@ | ||
/***/ }, | ||
/* 28 */ | ||
/* 27 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1374,7 +1351,7 @@ | ||
/***/ }, | ||
/* 29 */ | ||
/* 28 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var bindCallback = __webpack_require__(26), | ||
isIterateeCall = __webpack_require__(33), | ||
var bindCallback = __webpack_require__(25), | ||
isIterateeCall = __webpack_require__(32), | ||
restParam = __webpack_require__(9); | ||
@@ -1422,6 +1399,6 @@ | ||
/***/ }, | ||
/* 30 */ | ||
/* 29 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/* WEBPACK VAR INJECTION */(function(global) {var SetCache = __webpack_require__(17), | ||
/* WEBPACK VAR INJECTION */(function(global) {var SetCache = __webpack_require__(16), | ||
getNative = __webpack_require__(4); | ||
@@ -1451,6 +1428,6 @@ | ||
/***/ }, | ||
/* 31 */ | ||
/* 30 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var baseProperty = __webpack_require__(25); | ||
var baseProperty = __webpack_require__(24); | ||
@@ -1473,3 +1450,3 @@ /** | ||
/***/ }, | ||
/* 32 */ | ||
/* 31 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1503,3 +1480,3 @@ | ||
/***/ }, | ||
/* 33 */ | ||
/* 32 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1538,3 +1515,3 @@ | ||
/***/ }, | ||
/* 34 */ | ||
/* 33 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1546,3 +1523,3 @@ | ||
isLength = __webpack_require__(5), | ||
keysIn = __webpack_require__(38); | ||
keysIn = __webpack_require__(37); | ||
@@ -1587,3 +1564,3 @@ /** Used for native method references. */ | ||
/***/ }, | ||
/* 35 */ | ||
/* 34 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1632,6 +1609,6 @@ | ||
/***/ }, | ||
/* 36 */ | ||
/* 35 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var isFunction = __webpack_require__(35), | ||
var isFunction = __webpack_require__(34), | ||
isObjectLike = __webpack_require__(3); | ||
@@ -1687,8 +1664,8 @@ | ||
/***/ }, | ||
/* 37 */ | ||
/* 36 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var assignWith = __webpack_require__(19), | ||
baseAssign = __webpack_require__(20), | ||
createAssigner = __webpack_require__(29); | ||
var assignWith = __webpack_require__(18), | ||
baseAssign = __webpack_require__(19), | ||
createAssigner = __webpack_require__(28); | ||
@@ -1737,3 +1714,3 @@ /** | ||
/***/ }, | ||
/* 38 */ | ||
/* 37 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1808,3 +1785,3 @@ | ||
/***/ }, | ||
/* 39 */ | ||
/* 38 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -1834,4 +1811,49 @@ | ||
/***/ }, | ||
/* 39 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports["default"] = getForceUpdate; | ||
function traverseRenderedChildren(internalInstance, callback, argument) { | ||
callback(internalInstance, argument); | ||
if (internalInstance._renderedComponent) { | ||
traverseRenderedChildren(internalInstance._renderedComponent, callback, argument); | ||
} else { | ||
for (var key in internalInstance._renderedChildren) { | ||
if (internalInstance._renderedChildren.hasOwnProperty(key)) { | ||
traverseRenderedChildren(internalInstance._renderedChildren[key], callback, argument); | ||
} | ||
} | ||
} | ||
} | ||
function setPendingForceUpdate(internalInstance) { | ||
if (internalInstance._pendingForceUpdate === false) { | ||
internalInstance._pendingForceUpdate = true; | ||
} | ||
} | ||
function forceUpdateIfPending(internalInstance, React) { | ||
if (internalInstance._pendingForceUpdate === true) { | ||
var publicInstance = internalInstance._instance; | ||
React.Component.prototype.forceUpdate.call(publicInstance); | ||
} | ||
} | ||
function getForceUpdate(React) { | ||
return function (instance) { | ||
var internalInstance = instance._reactInternalInstance; | ||
traverseRenderedChildren(internalInstance, setPendingForceUpdate); | ||
traverseRenderedChildren(internalInstance, forceUpdateIfPending, React); | ||
}; | ||
} | ||
module.exports = exports["default"]; | ||
/***/ } | ||
/******/ ]) | ||
}); |
@@ -13,4 +13,4 @@ 'use strict'; | ||
var _getForceUpdate = require('./getForceUpdate'); | ||
var _reactDeepForceUpdate = require('react-deep-force-update'); | ||
exports.getForceUpdate = _interopRequire(_getForceUpdate); | ||
exports.getForceUpdate = _interopRequire(_reactDeepForceUpdate); |
{ | ||
"name": "react-proxy", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Proxies React components without unmounting or losing their state.", | ||
@@ -33,4 +33,5 @@ "main": "modules/index.js", | ||
"dependencies": { | ||
"lodash": "^3.7.0" | ||
"lodash": "^3.7.0", | ||
"react-deep-force-update": "^1.0.0" | ||
} | ||
} |
# React Proxy [](https://travis-ci.org/gaearon/react-proxy) [](https://www.npmjs.com/package/react-proxy) | ||
**Work in progress.** | ||
A generic React component proxy used as the new engine by React Hot Loader. | ||
Generic React component proxy. | ||
A future engine for React Hot Loader. | ||
## Requirements | ||
@@ -38,3 +35,5 @@ | ||
React.render(<ComponentVersion1 />, rootEl); | ||
React.render(<ComponentVersion2 />, rootEl); // will reset state and kill DOM :-( | ||
// Will reset state and kill DOM :-( | ||
React.render(<ComponentVersion2 />, rootEl); | ||
``` | ||
@@ -47,18 +46,61 @@ | ||
// Create a proxy object, given the initial React component class. | ||
const proxy = createProxy(ComponentVersion1); | ||
// Obtain a React class that acts exactly like the initial version. | ||
// This is what we'll use in our app instead of the real component class. | ||
const Proxy = proxy.get(); | ||
// Render the component (proxy, really). | ||
React.render(<Proxy />, rootEl); | ||
// will update the mounted instances' prototypes: | ||
// both DOM and state are perserved. | ||
// Point the proxy to the new React component class by calling update(). | ||
// Instances will stay mounted and their state will be intact, but their methods will be updated. | ||
// The update() method returns an array of mounted instances so we can do something with them. | ||
const mountedInstances = proxy.update(ComponentVersion2); | ||
// works with React Native and non-Component descendants | ||
// React Proxy also provides us with getForceUpdate() method that works even if the component | ||
// instance doesn't descend from React.Component, and doesn't have a forceUpdate() method. | ||
const forceUpdate = getForceUpdate(React); | ||
// Force-update all the affected instances! | ||
mountedInstances.forEach(forceUpdate); | ||
``` | ||
## Features | ||
* Supports both classic (`React.createClass()`) and modern (ES6 classes) style | ||
* Supports classes that don’t descend from `React.Component` | ||
* Supports classes with strict `shouldComponentUpdate` | ||
* Supports inherited and base classes (although you shouldn’t use inheritance with React) | ||
* Supports classic `createClass()` autobinding and modern [`autobind-decorator`](https://github.com/andreypopp/autobind-decorator) | ||
* Contains an extensive test suite to avoid regressions | ||
* Preserves `displayName` | ||
* Preserves enumerability and writability of methods | ||
* Preserves `toString()` of methods | ||
* Replaces instance getters and setters | ||
* Replaces instance methods preserving their identity | ||
* Replaces bound instance methods preserving their identity | ||
* Because identity is preserved, instance methods already scheduled for `setInterval` or `setTimeout` are updated | ||
* Replaces static getters and setters | ||
* Replaces unbound static methods | ||
* Replaces static properties unless they were overwritten by code | ||
## Known Limitations | ||
* Does not replace ES7 instance properties | ||
* Does not replace bound static methods | ||
* Replacing a method using [`autobind-decorator`](https://github.com/andreypopp/autobind-decorator) causes its identity to change | ||
## Contributing | ||
1. Clone the repository | ||
2. Run `npm install` | ||
3. Run `npm run test:watch` | ||
4. Take a look at the existing tests | ||
5. Add tests for the failing case you aim to fix and make them pass | ||
6. Submit a PR! | ||
## License | ||
MIT |
export { default as createProxy } from './createClassProxy'; | ||
export { default as getForceUpdate } from './getForceUpdate'; | ||
export { default as getForceUpdate } from 'react-deep-force-update'; |
81929
2.96%105
66.67%2
100%19
-9.52%2212
-0.18%+ Added