From 611b7fda8d38038e29febea65eac9f49cd6ea93a Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 17 Jan 2018 14:38:04 -0800 Subject: [PATCH 1/6] Added UNSAFE_ methods to create-class HAS_MANY list --- addons/create-react-class/factory.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/addons/create-react-class/factory.js b/addons/create-react-class/factory.js index c202f0b9168..1585dcc7c7d 100644 --- a/addons/create-react-class/factory.js +++ b/addons/create-react-class/factory.js @@ -204,6 +204,20 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ componentWillReceiveProps: 'DEFINE_MANY', + /** + * Replacement for (deprecated) `componentWillMount`. + * + * @optional + */ + UNSAFE_componentWillMount: 'DEFINE_MANY', + + /** + * Replacement for (deprecated) `componentWillReceiveProps`. + * + * @optional + */ + UNSAFE_componentWillReceiveProps: 'DEFINE_MANY', + /** * Invoked while deciding if the component should be updated as a result of * receiving new props, state and/or context. @@ -243,6 +257,13 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ componentWillUpdate: 'DEFINE_MANY', + /** + * Replacement for (deprecated) `shouldComponentUpdate`. + * + * @optional + */ + UNSAFE_shouldComponentUpdate: 'DEFINE_MANY', + /** * Invoked when the component's DOM representation has been updated. * From f0ac6efbcd0cfb29e99356270a41ea1e4d785012 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 17 Jan 2018 14:39:13 -0800 Subject: [PATCH 2/6] Added warning for UNSAFE_componentWillRecieveProps misspelling --- addons/create-react-class/factory.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/addons/create-react-class/factory.js b/addons/create-react-class/factory.js index 1585dcc7c7d..8bf1a28b2c6 100644 --- a/addons/create-react-class/factory.js +++ b/addons/create-react-class/factory.js @@ -873,6 +873,12 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component' ); + warning( + !Constructor.prototype.UNSAFE_componentWillRecieveProps, + '%s has a method called UNSAFE_componentWillRecieveProps(). ' + + 'Did you mean UNSAFE_componentWillReceiveProps()?', + spec.displayName || 'A component' + ); } // Reduce time spent doing lookups by setting these on the prototype. From bfb17caa944d83137e141f113b305970ce98196c Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Thu, 18 Jan 2018 09:53:49 -0800 Subject: [PATCH 3/6] Bumping create-react-class package version --- addons/create-react-class/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/create-react-class/package.json b/addons/create-react-class/package.json index 3c4ddf6c827..5c6d19c0198 100644 --- a/addons/create-react-class/package.json +++ b/addons/create-react-class/package.json @@ -1,6 +1,6 @@ { "name": "create-react-class", - "version": "15.6.2", + "version": "15.6.3", "description": "Legacy API for creating React components.", "main": "index.js", "license": "MIT", From c47c0832e92cc937a99ca7802f292e817236e6eb Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 19 Jan 2018 13:52:02 -0800 Subject: [PATCH 4/6] Added support for static getDerivedStateFromProps mixins --- addons/create-react-class/factory.js | 40 +++++++++++++++++----- addons/create-react-class/test.js | 51 ++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/addons/create-react-class/factory.js b/addons/create-react-class/factory.js index 8bf1a28b2c6..dbf0afaed83 100644 --- a/addons/create-react-class/factory.js +++ b/addons/create-react-class/factory.js @@ -121,6 +121,18 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ getDefaultProps: 'DEFINE_MANY_MERGED', + /** + * This method is invoked after a component is instantiated and when it + * receives new props. Return an object to update state in response to + * prop changes. Return null to indicate no change to state. + * + * If an object is returned, its keys will be merged into the existing state. + * + * @return {object || null} + * @optional + */ + getDerivedStateFromProps: 'DEFINE_MANY_MERGED', + /** * Invoked once before the component is mounted. The return value will be used * as the initial value of `this.state`. @@ -540,6 +552,7 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { if (!statics) { return; } + for (var name in statics) { var property = statics[name]; if (!statics.hasOwnProperty(name)) { @@ -556,14 +569,25 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { name ); - var isInherited = name in Constructor; - _invariant( - !isInherited, - 'ReactClass: You are attempting to define ' + - '`%s` on your component more than once. This conflict may be ' + - 'due to a mixin.', - name - ); + var isAlreadyDefined = name in Constructor; + if (isAlreadyDefined) { + var specPolicy = ReactClassInterface.hasOwnProperty(name) + ? ReactClassInterface[name] + : null; + + _invariant( + specPolicy === 'DEFINE_MANY_MERGED', + 'ReactClass: You are attempting to define ' + + '`%s` on your component more than once. This conflict may be ' + + 'due to a mixin.', + name + ); + + Constructor[name] = createMergedResultFunction(Constructor[name], property); + + return; + } + Constructor[name] = property; } } diff --git a/addons/create-react-class/test.js b/addons/create-react-class/test.js index 5218628c0b2..4273171860b 100644 --- a/addons/create-react-class/test.js +++ b/addons/create-react-class/test.js @@ -522,4 +522,55 @@ describe('ReactClass-spec', () => { 'to prevent memory leaks.' ); }); + + it('should support getInitialState mixin', () => { + const Component = createReactClass({ + mixins: [{ + getInitialState: function(props) { + return { + foo: 'foo' + }; + }, + }], + getInitialState: function(props) { + return { + bar: 'bar' + }; + }, + render: function() { + return
; + } + }); + const instance = renderIntoDocument(); + expect(instance.state.foo).toEqual('foo'); + expect(instance.state.bar).toEqual('bar'); + }); + + it('should merge return values for static getDerivedStateFromProps mixin', () => { + const Component = createReactClass({ + mixins: [{ + statics: { + getDerivedStateFromProps: function(props, prevState) { + return { + foo: 'foo' + }; + } + }, + }], + statics: { + getDerivedStateFromProps: function(props, prevState) { + return { + bar: 'bar' + }; + } + }, + render: function() { + return
; + } + }); + + const state = Component.getDerivedStateFromProps(); + expect(state.foo).toEqual('foo'); + expect(state.bar).toEqual('bar'); + }); }); From 4644f99da8e88ace9a2d18895861daece746040f Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 19 Jan 2018 13:55:42 -0800 Subject: [PATCH 5/6] Moved static gDSFP spec into separte spec config --- addons/create-react-class/factory.js | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/addons/create-react-class/factory.js b/addons/create-react-class/factory.js index dbf0afaed83..1417a828281 100644 --- a/addons/create-react-class/factory.js +++ b/addons/create-react-class/factory.js @@ -121,18 +121,6 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ getDefaultProps: 'DEFINE_MANY_MERGED', - /** - * This method is invoked after a component is instantiated and when it - * receives new props. Return an object to update state in response to - * prop changes. Return null to indicate no change to state. - * - * If an object is returned, its keys will be merged into the existing state. - * - * @return {object || null} - * @optional - */ - getDerivedStateFromProps: 'DEFINE_MANY_MERGED', - /** * Invoked once before the component is mounted. The return value will be used * as the initial value of `this.state`. @@ -318,6 +306,23 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { updateComponent: 'OVERRIDE_BASE' }; + /** + * Similar to ReactClassInterface but for static methods. + */ + var ReactClassStaticInterface = { + /** + * This method is invoked after a component is instantiated and when it + * receives new props. Return an object to update state in response to + * prop changes. Return null to indicate no change to state. + * + * If an object is returned, its keys will be merged into the existing state. + * + * @return {object || null} + * @optional + */ + getDerivedStateFromProps: 'DEFINE_MANY_MERGED' + }; + /** * Mapping from class specification keys to special processing functions. * @@ -571,8 +576,8 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { var isAlreadyDefined = name in Constructor; if (isAlreadyDefined) { - var specPolicy = ReactClassInterface.hasOwnProperty(name) - ? ReactClassInterface[name] + var specPolicy = ReactClassStaticInterface.hasOwnProperty(name) + ? ReactClassStaticInterface[name] : null; _invariant( From 29cdc5aca5a9b35ed8b21cb03416a59bd6722122 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 19 Jan 2018 14:11:57 -0800 Subject: [PATCH 6/6] Fixed UNSAFE_shouldComponentUpdate -> UNSAFE_componentWillUpdate --- addons/create-react-class/factory.js | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/addons/create-react-class/factory.js b/addons/create-react-class/factory.js index 1417a828281..830c414815e 100644 --- a/addons/create-react-class/factory.js +++ b/addons/create-react-class/factory.js @@ -204,20 +204,6 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ componentWillReceiveProps: 'DEFINE_MANY', - /** - * Replacement for (deprecated) `componentWillMount`. - * - * @optional - */ - UNSAFE_componentWillMount: 'DEFINE_MANY', - - /** - * Replacement for (deprecated) `componentWillReceiveProps`. - * - * @optional - */ - UNSAFE_componentWillReceiveProps: 'DEFINE_MANY', - /** * Invoked while deciding if the component should be updated as a result of * receiving new props, state and/or context. @@ -257,13 +243,6 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ componentWillUpdate: 'DEFINE_MANY', - /** - * Replacement for (deprecated) `shouldComponentUpdate`. - * - * @optional - */ - UNSAFE_shouldComponentUpdate: 'DEFINE_MANY', - /** * Invoked when the component's DOM representation has been updated. * @@ -291,6 +270,27 @@ function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { */ componentWillUnmount: 'DEFINE_MANY', + /** + * Replacement for (deprecated) `componentWillMount`. + * + * @optional + */ + UNSAFE_componentWillMount: 'DEFINE_MANY', + + /** + * Replacement for (deprecated) `componentWillReceiveProps`. + * + * @optional + */ + UNSAFE_componentWillReceiveProps: 'DEFINE_MANY', + + /** + * Replacement for (deprecated) `componentWillUpdate`. + * + * @optional + */ + UNSAFE_componentWillUpdate: 'DEFINE_MANY', + // ==== Advanced methods ==== /**