Comparing version 1.0.3 to 1.1.0
# Changelog | ||
### 1.1.0 | ||
* It is now possible to return an entirely new state from a producer as well. Immer will verify that you didn't both change the draft and returned a new state. Implements [#103](https://github.com/mweststrate/immer/issues/103) | ||
* Improved TypeScript typings. See [#99](https://github.com/mweststrate/immer/pull/99) by [Anton Fedchenko](https://github.com/kompot) | ||
### 1.0.3 (15-Feb-2018) | ||
* Fixed dectection of production mode. Fixes [#95](https://github.com/mweststrate/immer/issues/95) | ||
* Fixed detection of production mode. Fixes [#95](https://github.com/mweststrate/immer/issues/95) | ||
@@ -7,0 +12,0 @@ ### 1.0.2 (13-Feb-2018) |
@@ -18,14 +18,14 @@ /** | ||
// curried invocations | ||
export default function<S = any>( | ||
recipe: (this: S, draftState: S, ...extraArgs: any[]) => void | ||
): (currentState: S, ...extraArgs: any[]) => S | ||
export default function<S = any, A = any>( | ||
recipe: (this: S, draftState: S, a: A) => void | ||
): (currentState: S, a: A) => S | ||
export default function<S = any, A = any, B = any>( | ||
recipe: (this: S, draftState: S, a: A, b: B) => void | ||
): (currentState: S, a: A, b: B) => S | ||
export default function<S = any, A = any, B = any, C = any>( | ||
recipe: (this: S, draftState: S, a: A, b: B, c: C) => void | ||
): (currentState: S, a: A, b: B, c: C) => S | ||
export default function<S = any, A = any, B = any>( | ||
recipe: (this: S, draftState: S, a: A, b: B) => void | ||
): (currentState: S, a: A, b: B) => S | ||
export default function<S = any, A = any>( | ||
recipe: (this: S, draftState: S, a: A) => void | ||
): (currentState: S) => S | ||
export default function<S = any>( | ||
recipe: (this: S, draftState: S, ...extraArgs: any[]) => void | ||
): (currentState: S, ...extraArgs: any[]) => S | ||
@@ -32,0 +32,0 @@ /** |
@@ -13,7 +13,9 @@ 'use strict'; | ||
var RETURNED_AND_MODIFIED_ERROR = "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft."; | ||
function verifyMinified() {} | ||
var inProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production" || verifyMinified.name !== "verifyMinified"; | ||
var autoFreeze = !inProduction; | ||
var useProxies = typeof Proxy !== "undefined"; | ||
@@ -120,7 +122,4 @@ | ||
function verifyReturnValue(value) { | ||
// values either than undefined will trigger warning; | ||
if (value !== undefined) console.warn("Immer callback expects no return value. However " + (typeof value === "undefined" ? "undefined" : _typeof(value)) + " was returned"); | ||
} | ||
function is(x, y) { | ||
@@ -246,7 +245,13 @@ // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js | ||
// create proxy for root | ||
var rootClone = createProxy(undefined, baseState); | ||
var rootProxy = createProxy(undefined, baseState); | ||
// execute the thunk | ||
verifyReturnValue(producer.call(rootClone, rootClone)); | ||
var returnValue = producer.call(rootProxy, rootProxy); | ||
// and finalize the modified proxy | ||
var res = finalize(rootClone); | ||
var result = finalize(rootProxy); | ||
// check whether the draft was modified and/or a value was returned | ||
if (returnValue !== undefined && returnValue !== rootProxy) { | ||
// something was returned, and it wasn't the proxy itself | ||
if (rootProxy[PROXY_STATE].modified) throw new Error(RETURNED_AND_MODIFIED_ERROR); | ||
result = returnValue; | ||
} | ||
// revoke all proxies | ||
@@ -256,3 +261,3 @@ each(proxies, function (_, p) { | ||
}); | ||
return res; | ||
return result; | ||
} finally { | ||
@@ -382,5 +387,5 @@ proxies = previousProxies; | ||
// create proxy for root | ||
var rootClone = createProxy$1(undefined, baseState); | ||
var rootProxy = createProxy$1(undefined, baseState); | ||
// execute the thunk | ||
verifyReturnValue(producer.call(rootClone, rootClone)); | ||
var returnValue = producer.call(rootProxy, rootProxy); | ||
// and finalize the modified proxy | ||
@@ -393,3 +398,9 @@ each(states, function (_, state) { | ||
markChanges(); | ||
var res = finalize(rootClone); | ||
var result = finalize(rootProxy); | ||
// check whether the draft was modified and/or a value was returned | ||
if (returnValue !== undefined && returnValue !== rootProxy) { | ||
// something was returned, and it wasn't the proxy itself | ||
if (rootProxy[PROXY_STATE].modified) throw new Error(RETURNED_AND_MODIFIED_ERROR); | ||
result = returnValue; | ||
} | ||
// make sure all proxies become unusable | ||
@@ -399,3 +410,3 @@ each(states, function (_, state) { | ||
}); | ||
return res; | ||
return result; | ||
} finally { | ||
@@ -459,6 +470,8 @@ states = prevStates; | ||
if (arguments.length !== 2) throw new Error("produce expects 1 or 2 arguments, got " + arguments.length); | ||
if (!isProxyable(baseState)) throw new Error("the first argument to produce should be a plain object or array, got " + (typeof baseState === "undefined" ? "undefined" : _typeof(baseState))); | ||
if (typeof producer !== "function") throw new Error("the second argument to produce should be a function"); | ||
} | ||
// it state is a primitive, don't bother proxying at all and just return whatever the producer returns on that value | ||
if ((typeof baseState === "undefined" ? "undefined" : _typeof(baseState)) !== "object" || baseState === null) return producer(baseState); | ||
if (!isProxyable(baseState)) throw new Error("the first argument to an immer producer should be a primitive, plain object or array, got " + (typeof baseState === "undefined" ? "undefined" : _typeof(baseState)) + ": \"" + baseState + "\""); | ||
return getUseProxies() ? produceProxy(baseState, producer) : produceEs5(baseState, producer); | ||
@@ -465,0 +478,0 @@ } |
@@ -9,7 +9,9 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
var RETURNED_AND_MODIFIED_ERROR = "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft."; | ||
function verifyMinified() {} | ||
var inProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production" || verifyMinified.name !== "verifyMinified"; | ||
var autoFreeze = !inProduction; | ||
var useProxies = typeof Proxy !== "undefined"; | ||
@@ -116,7 +118,4 @@ | ||
function verifyReturnValue(value) { | ||
// values either than undefined will trigger warning; | ||
if (value !== undefined) console.warn("Immer callback expects no return value. However " + (typeof value === "undefined" ? "undefined" : _typeof(value)) + " was returned"); | ||
} | ||
function is(x, y) { | ||
@@ -242,7 +241,13 @@ // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js | ||
// create proxy for root | ||
var rootClone = createProxy(undefined, baseState); | ||
var rootProxy = createProxy(undefined, baseState); | ||
// execute the thunk | ||
verifyReturnValue(producer.call(rootClone, rootClone)); | ||
var returnValue = producer.call(rootProxy, rootProxy); | ||
// and finalize the modified proxy | ||
var res = finalize(rootClone); | ||
var result = finalize(rootProxy); | ||
// check whether the draft was modified and/or a value was returned | ||
if (returnValue !== undefined && returnValue !== rootProxy) { | ||
// something was returned, and it wasn't the proxy itself | ||
if (rootProxy[PROXY_STATE].modified) throw new Error(RETURNED_AND_MODIFIED_ERROR); | ||
result = returnValue; | ||
} | ||
// revoke all proxies | ||
@@ -252,3 +257,3 @@ each(proxies, function (_, p) { | ||
}); | ||
return res; | ||
return result; | ||
} finally { | ||
@@ -378,5 +383,5 @@ proxies = previousProxies; | ||
// create proxy for root | ||
var rootClone = createProxy$1(undefined, baseState); | ||
var rootProxy = createProxy$1(undefined, baseState); | ||
// execute the thunk | ||
verifyReturnValue(producer.call(rootClone, rootClone)); | ||
var returnValue = producer.call(rootProxy, rootProxy); | ||
// and finalize the modified proxy | ||
@@ -389,3 +394,9 @@ each(states, function (_, state) { | ||
markChanges(); | ||
var res = finalize(rootClone); | ||
var result = finalize(rootProxy); | ||
// check whether the draft was modified and/or a value was returned | ||
if (returnValue !== undefined && returnValue !== rootProxy) { | ||
// something was returned, and it wasn't the proxy itself | ||
if (rootProxy[PROXY_STATE].modified) throw new Error(RETURNED_AND_MODIFIED_ERROR); | ||
result = returnValue; | ||
} | ||
// make sure all proxies become unusable | ||
@@ -395,3 +406,3 @@ each(states, function (_, state) { | ||
}); | ||
return res; | ||
return result; | ||
} finally { | ||
@@ -455,6 +466,8 @@ states = prevStates; | ||
if (arguments.length !== 2) throw new Error("produce expects 1 or 2 arguments, got " + arguments.length); | ||
if (!isProxyable(baseState)) throw new Error("the first argument to produce should be a plain object or array, got " + (typeof baseState === "undefined" ? "undefined" : _typeof(baseState))); | ||
if (typeof producer !== "function") throw new Error("the second argument to produce should be a function"); | ||
} | ||
// it state is a primitive, don't bother proxying at all and just return whatever the producer returns on that value | ||
if ((typeof baseState === "undefined" ? "undefined" : _typeof(baseState)) !== "object" || baseState === null) return producer(baseState); | ||
if (!isProxyable(baseState)) throw new Error("the first argument to an immer producer should be a primitive, plain object or array, got " + (typeof baseState === "undefined" ? "undefined" : _typeof(baseState)) + ": \"" + baseState + "\""); | ||
return getUseProxies() ? produceProxy(baseState, producer) : produceEs5(baseState, producer); | ||
@@ -461,0 +474,0 @@ } |
@@ -1,2 +0,2 @@ | ||
var e,r;e=this,r=function(e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n="undefined"!=typeof Symbol?Symbol("immer-proxy-state"):"__$immer_state";var t=!("undefined"!=typeof process&&"production"===process.env.NODE_ENV||"verifyMinified"!==function(){}.name),o="undefined"!=typeof Proxy;function i(e){return!!e&&!!e[n]}function f(e){if(!e)return!1;if("object"!==(void 0===e?"undefined":r(e)))return!1;if(Array.isArray(e))return!0;var n=Object.getPrototypeOf(e);return null===n||n===Object.prototype}function u(e){return t&&Object.freeze(e),e}function a(e){return Array.isArray(e)?e.slice():void 0===e.__proto__?Object.assign(Object.create(null),e):Object.assign({},e)}function c(e,r){if(Array.isArray(e))for(var n=0;n<e.length;n++)r(n,e[n]);else for(var t in e)r(t,e[t])}function s(e,r){return Object.prototype.hasOwnProperty.call(e,r)}function p(e){if(i(e)){var r=e[n];return!0===r.modified?!0===r.finalized?r.copy:(r.finalized=!0,t=o?r.copy:r.copy=a(e),s=r.base,c(t,function(e,r){r!==s[e]&&(t[e]=p(r))}),u(t)):r.base}var t,s;return function e(r){if(!f(r))return;if(Object.isFrozen(r))return;c(r,function(n,t){i(t)?r[n]=p(t):e(t)});u(r)}(e),e}function y(e){void 0!==e&&console.warn("Immer callback expects no return value. However "+(void 0===e?"undefined":r(e))+" was returned")}function d(e,r){return e===r?0!==e||1/e==1/r:e!=e&&r!=r}var l=null,b={get:function(e,r){if(r===n)return e;if(e.modified){var t=e.copy[r];return t===e.base[r]&&f(t)?e.copy[r]=g(e,t):t}if(s(e.proxies,r))return e.proxies[r];var o=e.base[r];return!i(o)&&f(o)?e.proxies[r]=g(e,o):o},has:function(e,r){return r in m(e)},ownKeys:function(e){return Reflect.ownKeys(m(e))},set:function(e,r,n){if(!e.modified){if(r in e.base&&d(e.base[r],n)||s(e.proxies,r)&&e.proxies[r]===n)return!0;h(e)}return e.copy[r]=n,!0},deleteProperty:function(e,r){return h(e),delete e.copy[r],!0},getOwnPropertyDescriptor:function(e,r){var n=e.modified?e.copy:s(e.proxies,r)?e.proxies:e.base,t=Reflect.getOwnPropertyDescriptor(n,r);!t||Array.isArray(n)&&"length"===r||(t.configurable=!0);return t},defineProperty:function(){throw new Error("Immer does currently not support defining properties on draft objects")},setPrototypeOf:function(){throw new Error("Don't even try this...")}},v={};function m(e){return!0===e.modified?e.copy:e.base}function h(e){e.modified||(e.modified=!0,e.copy=a(e.base),Object.assign(e.copy,e.proxies),e.parent&&h(e.parent))}function g(e,r){var n={modified:!1,finalized:!1,parent:e,base:r,copy:void 0,proxies:{}},t=Array.isArray(r)?Proxy.revocable([n],v):Proxy.revocable(n,b);return l.push(t),t.proxy}c(b,function(e,r){v[e]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)}});var w={},x=null;function j(e){return e.hasCopy?e.copy:e.base}function O(e){e.modified||(e.modified=!0,e.parent&&O(e.parent))}function P(e){e.hasCopy||(e.hasCopy=!0,e.copy=a(e.base))}function A(e,r){var t=a(r);c(r,function(e){var r;Object.defineProperty(t,""+e,w[r=""+e]||(w[r]={configurable:!0,enumerable:!0,get:function(){return function(e,r){z(e);var n=j(e)[r];return!e.finalizing&&n===e.base[r]&&f(n)?(P(e),e.copy[r]=A(e,n)):n}(this[n],r)},set:function(e){!function(e,r,n){if(z(e),!e.modified){if(d(j(e)[r],n))return;O(e),P(e)}e.copy[r]=n}(this[n],r,e)}}))});var o,i,u,s={modified:!1,hasCopy:!1,parent:e,base:r,proxy:t,copy:void 0,finished:!1,finalizing:!1,finalized:!1};return o=t,i=n,u=s,Object.defineProperty(o,i,{value:u,enumerable:!1,writable:!0}),x.push(s),t}function z(e){if(!0===e.finished)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process?")}function _(e,n){var t=x;x=[];try{var o=A(void 0,e);y(n.call(o,o)),c(x,function(e,r){r.finalizing=!0}),function(){for(var e=x.length-1;e>=0;e--){var n=x[e];!1===n.modified&&(Array.isArray(n.base)?(f=n).proxy.length!==f.base.length&&O(n):(t=n,o=Object.keys(t.base),i=Object.keys(t.proxy),function(e,n){if(d(e,n))return!0;if("object"!==(void 0===e?"undefined":r(e))||null===e||"object"!==(void 0===n?"undefined":r(n))||null===n)return!1;var t=Object.keys(e),o=Object.keys(n);if(t.length!==o.length)return!1;for(var i=0;i<t.length;i++)if(!hasOwnProperty.call(n,t[i])||!d(e[t[i]],n[t[i]]))return!1;return!0}(o,i)||O(n)))}var t,o,i,f}();var i=p(o);return c(x,function(e,r){r.finished=!0}),i}finally{x=t}}e.default=function e(n,t){if(1===arguments.length){var i=n;if("function"!=typeof i)throw new Error("if produce is called with 1 argument, the first argument should be a function");return function(){var r=arguments;return e(r[0],function(e){r[0]=e,i.apply(e,r)})}}if(2!==arguments.length)throw new Error("produce expects 1 or 2 arguments, got "+arguments.length);if(!f(n))throw new Error("the first argument to produce should be a plain object or array, got "+(void 0===n?"undefined":r(n)));if("function"!=typeof t)throw new Error("the second argument to produce should be a function");return o?function(e,r){var n=l;l=[];try{var t=g(void 0,e);y(r.call(t,t));var o=p(t);return c(l,function(e,r){return r.revoke()}),o}finally{l=n}}(n,t):_(n,t)},e.setAutoFreeze=function(e){t=e},e.setUseProxies=function(e){o=e},Object.defineProperty(e,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r(e.immer={}); | ||
var e,r;e=this,r=function(e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n="undefined"!=typeof Symbol?Symbol("immer-proxy-state"):"__$immer_state",t="An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.";var o=!("undefined"!=typeof process&&"production"===process.env.NODE_ENV||"verifyMinified"!==function(){}.name),i="undefined"!=typeof Proxy;function f(e){return!!e&&!!e[n]}function u(e){if(!e)return!1;if("object"!==(void 0===e?"undefined":r(e)))return!1;if(Array.isArray(e))return!0;var n=Object.getPrototypeOf(e);return null===n||n===Object.prototype}function a(e){return o&&Object.freeze(e),e}function c(e){return Array.isArray(e)?e.slice():void 0===e.__proto__?Object.assign(Object.create(null),e):Object.assign({},e)}function s(e,r){if(Array.isArray(e))for(var n=0;n<e.length;n++)r(n,e[n]);else for(var t in e)r(t,e[t])}function d(e,r){return Object.prototype.hasOwnProperty.call(e,r)}function p(e){if(f(e)){var r=e[n];return!0===r.modified?!0===r.finalized?r.copy:(r.finalized=!0,t=i?r.copy:r.copy=c(e),o=r.base,s(t,function(e,r){r!==o[e]&&(t[e]=p(r))}),a(t)):r.base}var t,o;return function e(r){if(!u(r))return;if(Object.isFrozen(r))return;s(r,function(n,t){f(t)?r[n]=p(t):e(t)});a(r)}(e),e}function y(e,r){return e===r?0!==e||1/e==1/r:e!=e&&r!=r}var l=null,b={get:function(e,r){if(r===n)return e;if(e.modified){var t=e.copy[r];return t===e.base[r]&&u(t)?e.copy[r]=g(e,t):t}if(d(e.proxies,r))return e.proxies[r];var o=e.base[r];return!f(o)&&u(o)?e.proxies[r]=g(e,o):o},has:function(e,r){return r in m(e)},ownKeys:function(e){return Reflect.ownKeys(m(e))},set:function(e,r,n){if(!e.modified){if(r in e.base&&y(e.base[r],n)||d(e.proxies,r)&&e.proxies[r]===n)return!0;h(e)}return e.copy[r]=n,!0},deleteProperty:function(e,r){return h(e),delete e.copy[r],!0},getOwnPropertyDescriptor:function(e,r){var n=e.modified?e.copy:d(e.proxies,r)?e.proxies:e.base,t=Reflect.getOwnPropertyDescriptor(n,r);!t||Array.isArray(n)&&"length"===r||(t.configurable=!0);return t},defineProperty:function(){throw new Error("Immer does currently not support defining properties on draft objects")},setPrototypeOf:function(){throw new Error("Don't even try this...")}},v={};function m(e){return!0===e.modified?e.copy:e.base}function h(e){e.modified||(e.modified=!0,e.copy=c(e.base),Object.assign(e.copy,e.proxies),e.parent&&h(e.parent))}function g(e,r){var n={modified:!1,finalized:!1,parent:e,base:r,copy:void 0,proxies:{}},t=Array.isArray(r)?Proxy.revocable([n],v):Proxy.revocable(n,b);return l.push(t),t.proxy}s(b,function(e,r){v[e]=function(){return arguments[0]=arguments[0][0],r.apply(this,arguments)}});var w={},j=null;function x(e){return e.hasCopy?e.copy:e.base}function O(e){e.modified||(e.modified=!0,e.parent&&O(e.parent))}function P(e){e.hasCopy||(e.hasCopy=!0,e.copy=c(e.base))}function A(e,r){var t=c(r);s(r,function(e){var r;Object.defineProperty(t,""+e,w[r=""+e]||(w[r]={configurable:!0,enumerable:!0,get:function(){return function(e,r){E(e);var n=x(e)[r];return!e.finalizing&&n===e.base[r]&&u(n)?(P(e),e.copy[r]=A(e,n)):n}(this[n],r)},set:function(e){!function(e,r,n){if(E(e),!e.modified){if(y(x(e)[r],n))return;O(e),P(e)}e.copy[r]=n}(this[n],r,e)}}))});var o,i,f,a={modified:!1,hasCopy:!1,parent:e,base:r,proxy:t,copy:void 0,finished:!1,finalizing:!1,finalized:!1};return o=t,i=n,f=a,Object.defineProperty(o,i,{value:f,enumerable:!1,writable:!0}),j.push(a),t}function E(e){if(!0===e.finished)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process?")}function z(e,o){var i=j;j=[];try{var f=A(void 0,e),u=o.call(f,f);s(j,function(e,r){r.finalizing=!0}),function(){for(var e=j.length-1;e>=0;e--){var n=j[e];!1===n.modified&&(Array.isArray(n.base)?(f=n).proxy.length!==f.base.length&&O(n):(t=n,o=Object.keys(t.base),i=Object.keys(t.proxy),function(e,n){if(y(e,n))return!0;if("object"!==(void 0===e?"undefined":r(e))||null===e||"object"!==(void 0===n?"undefined":r(n))||null===n)return!1;var t=Object.keys(e),o=Object.keys(n);if(t.length!==o.length)return!1;for(var i=0;i<t.length;i++)if(!hasOwnProperty.call(n,t[i])||!y(e[t[i]],n[t[i]]))return!1;return!0}(o,i)||O(n)))}var t,o,i,f}();var a=p(f);if(void 0!==u&&u!==f){if(f[n].modified)throw new Error(t);a=u}return s(j,function(e,r){r.finished=!0}),a}finally{j=i}}e.default=function e(o,f){if(1===arguments.length){var a=o;if("function"!=typeof a)throw new Error("if produce is called with 1 argument, the first argument should be a function");return function(){var r=arguments;return e(r[0],function(e){r[0]=e,a.apply(e,r)})}}if(2!==arguments.length)throw new Error("produce expects 1 or 2 arguments, got "+arguments.length);if("function"!=typeof f)throw new Error("the second argument to produce should be a function");if("object"!==(void 0===o?"undefined":r(o))||null===o)return f(o);if(!u(o))throw new Error("the first argument to an immer producer should be a primitive, plain object or array, got "+(void 0===o?"undefined":r(o))+': "'+o+'"');return i?function(e,r){var o=l;l=[];try{var i=g(void 0,e),f=r.call(i,i),u=p(i);if(void 0!==f&&f!==i){if(i[n].modified)throw new Error(t);u=f}return s(l,function(e,r){return r.revoke()}),u}finally{l=o}}(o,f):z(o,f)},e.setAutoFreeze=function(e){o=e},e.setUseProxies=function(e){i=e},Object.defineProperty(e,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?r(exports):"function"==typeof define&&define.amd?define(["exports"],r):r(e.immer={}); | ||
//# sourceMappingURL=immer.umd.js.map |
{ | ||
"name": "immer", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"description": "Create your next immutable state by mutating the current one", | ||
@@ -5,0 +5,0 @@ "main": "dist/immer.js", |
@@ -140,7 +140,36 @@ # Immer | ||
## React.setState example | ||
Deep updates in the state of React components can be greatly simplified as well by using immer. | ||
Take for example the following onClick handlers (Try in [codesandbox](https://codesandbox.io/s/m4yp57632j)): | ||
```javascript | ||
/** | ||
* Classic React.setState with a deep merge | ||
*/ | ||
onBirthDayClick1 = () => { | ||
this.setState((prevState)=>({ | ||
user: { | ||
...prevState.user, | ||
age: prevState.user.age + 1 | ||
} | ||
})) | ||
} | ||
/** | ||
* ...But, since setState accepts functions, | ||
* we can just create a curried producer and further simplify! | ||
*/ | ||
onBirthDayClick2 = () => { | ||
this.setState(produce(draft => { | ||
draft.user.age += 1 | ||
}) | ||
} | ||
``` | ||
## Currying | ||
`produce` can be called with one or two arguments. | ||
The one argument version is intended to be used as currying. This means that you get a pre-pound producer, that only needs a state to produce the value from. | ||
The producer function get's passed in the draft, and any further arguments that were passed to the curried function. | ||
The one argument version is intended to be used for currying. This means that you get a pre-bound producer that only needs a state to produce the value from. | ||
The producer function gets passed in the draft, and any further arguments that were passed to the curried function. | ||
@@ -188,2 +217,45 @@ For example: | ||
## Returning data from producers | ||
It is not needed to return anything from a producer, as Immer will return the (finalized) version of the `draft` anyway. | ||
However, it allowed to just `return draft`. | ||
It is also allowed to return abritrarily other data from the producer function. But _only_ if you didn't modify the draft. | ||
This can be useful to produce an entirely new state. Some examples: | ||
```javascript | ||
const userReducer = produce((draft, action) => { | ||
switch (action.type) { | ||
case "renameUser": | ||
// OK: we modify the current state | ||
draft.users[action.payload.id].name = action.payload.name | ||
return draft // same as just 'return' | ||
case "loadUsers": | ||
// OK: we return an entirely new state | ||
return action.payload | ||
case "adduser-1": | ||
// NOT OK: This doesn't do change the draft nor return a new state! | ||
// It doesn't modify the draft (it just redeclares it) | ||
// In fact, this just doesn't do anything at all | ||
draft = { users: [...draft.users, action.payload]} | ||
return | ||
case "adduser-2": | ||
// NOT OK: modifying draft *and* returning a new state | ||
draft.userCount += 1 | ||
return { users: [...draft.users, action.payload] } | ||
case "adduser-3": | ||
// OK: returning a new state. But, unnecessary complex and expensive | ||
return { | ||
userCount: draft.userCount + 1, | ||
users: [...draft.users, action.payload] | ||
} | ||
case "adduser-4": | ||
// OK: the immer way | ||
draft.userCount += 1 | ||
draft.push(action.payload) | ||
return | ||
} | ||
}) | ||
``` | ||
## Using `this` | ||
@@ -223,2 +295,3 @@ | ||
1. Don't redefine draft like, `draft = myCoolNewState`. Instead, either modify the `draft` or return a new state. See [Returning data from producers](#returning-data-from-producers). | ||
1. Currently, Immer only supports plain objects and arrays. PRs are welcome for more language built-in types like `Map` and `Set`. | ||
@@ -225,0 +298,0 @@ 2. Immer only processes native arrays and plain objects (with a prototype of `null` or `Object`). Any other type of value will be treated verbatim! So if you modify a `Map` or `Buffer` (or whatever complex object from the draft state), the changes will be persisted. But, both in your new and old state! So, in such cases, make sure to always produce fresh instances if you want to keep your state truly immutable. |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
147155
895
368