diff --git a/src/addons/ReactWithAddons.js b/src/addons/ReactWithAddons.js index 4d556e92234..ae6890a3f82 100644 --- a/src/addons/ReactWithAddons.js +++ b/src/addons/ReactWithAddons.js @@ -11,7 +11,6 @@ 'use strict'; -var LinkedStateMixin = require('LinkedStateMixin'); var React = require('React'); var ReactAddonsDOMDependencies = require('ReactAddonsDOMDependencies'); var ReactComponentWithPureRenderMixin = @@ -25,7 +24,6 @@ var update = require('update'); React.addons = { CSSTransitionGroup: ReactCSSTransitionGroup, - LinkedStateMixin: LinkedStateMixin, PureRenderMixin: ReactComponentWithPureRenderMixin, TransitionGroup: ReactTransitionGroup, diff --git a/src/addons/link/LinkedStateMixin.js b/src/addons/link/LinkedStateMixin.js deleted file mode 100644 index 9e446f48364..00000000000 --- a/src/addons/link/LinkedStateMixin.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule LinkedStateMixin - */ - -'use strict'; - -var ReactLink = require('ReactLink'); -var ReactStateSetters = require('ReactStateSetters'); - -/** - * A simple mixin around ReactLink.forState(). - * See https://facebook.github.io/react/docs/two-way-binding-helpers.html - */ -var LinkedStateMixin = { - /** - * Create a ReactLink that's linked to part of this component's state. The - * ReactLink will have the current value of this.state[key] and will call - * setState() when a change is requested. - * - * @param {string} key state key to update. - * @return {ReactLink} ReactLink instance linking to the state. - */ - linkState: function(key) { - return new ReactLink( - this.state[key], - ReactStateSetters.createStateKeySetter(this, key) - ); - }, -}; - -module.exports = LinkedStateMixin; diff --git a/src/addons/link/ReactLink.js b/src/addons/link/ReactLink.js deleted file mode 100644 index d327b4f8ecb..00000000000 --- a/src/addons/link/ReactLink.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ReactLink - */ - -'use strict'; - -/** - * ReactLink encapsulates a common pattern in which a component wants to modify - * a prop received from its parent. ReactLink allows the parent to pass down a - * value coupled with a callback that, when invoked, expresses an intent to - * modify that value. For example: - * - * React.createClass({ - * getInitialState: function() { - * return {value: ''}; - * }, - * render: function() { - * var valueLink = new ReactLink(this.state.value, this._handleValueChange); - * return ; - * }, - * _handleValueChange: function(newValue) { - * this.setState({value: newValue}); - * } - * }); - * - * We have provided some sugary mixins to make the creation and - * consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin. - */ - -var React = require('React'); - -/** - * Deprecated: An an easy way to express two-way binding with React. - * See https://facebook.github.io/react/docs/two-way-binding-helpers.html - * - * @param {*} value current value of the link - * @param {function} requestChange callback to request a change - */ -function ReactLink(value, requestChange) { - this.value = value; - this.requestChange = requestChange; -} - -/** - * Creates a PropType that enforces the ReactLink API and optionally checks the - * type of the value being passed inside the link. Example: - * - * MyComponent.propTypes = { - * tabIndexLink: ReactLink.PropTypes.link(React.PropTypes.number) - * } - */ -function createLinkTypeChecker(linkType) { - var shapes = { - value: linkType === undefined ? - React.PropTypes.any.isRequired : - linkType.isRequired, - requestChange: React.PropTypes.func.isRequired, - }; - return React.PropTypes.shape(shapes); -} - -ReactLink.PropTypes = { - link: createLinkTypeChecker, -}; - -module.exports = ReactLink; diff --git a/src/addons/link/__tests__/LinkedStateMixin-test.js b/src/addons/link/__tests__/LinkedStateMixin-test.js deleted file mode 100644 index 1d6fa18aff8..00000000000 --- a/src/addons/link/__tests__/LinkedStateMixin-test.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails react-core - */ - -'use strict'; - - -describe('LinkedStateMixin', () => { - var LinkedStateMixin; - var React; - var ReactTestUtils; - - beforeEach(() => { - LinkedStateMixin = require('LinkedStateMixin'); - React = require('React'); - ReactTestUtils = require('ReactTestUtils'); - }); - - it('should create a ReactLink for state', () => { - var Component = React.createClass({ - mixins: [LinkedStateMixin], - - getInitialState: function() { - return {value: 'initial value'}; - }, - - render: function() { - return value is {this.state.value}; - }, - }); - var component = ReactTestUtils.renderIntoDocument(); - var link = component.linkState('value'); - expect(component.state.value).toBe('initial value'); - expect(link.value).toBe('initial value'); - link.requestChange('new value'); - expect(component.state.value).toBe('new value'); - expect(component.linkState('value').value).toBe('new value'); - }); -}); diff --git a/src/addons/link/__tests__/ReactLinkPropTypes-test.js b/src/addons/link/__tests__/ReactLinkPropTypes-test.js deleted file mode 100644 index d4e3a9e5cb3..00000000000 --- a/src/addons/link/__tests__/ReactLinkPropTypes-test.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails react-core - */ - -'use strict'; - -var emptyFunction = require('emptyFunction'); -var LinkPropTypes = require('ReactLink').PropTypes; -var React = require('React'); - -var invalidMessage = 'Invalid prop `testProp` supplied to `testComponent`.'; -var requiredMessage = 'The prop `testProp` is marked as required in ' + - '`testComponent`, but its value is `undefined`.'; - -function typeCheckFail(declaration, value, message) { - var props = {testProp: value}; - var error = declaration( - props, - 'testProp', - 'testComponent', - 'prop', - ); - expect(error instanceof Error).toBe(true); - expect(error.message).toBe(message); -} - -function typeCheckPass(declaration, value) { - var props = {testProp: value}; - var error = declaration( - props, - 'testProp', - 'testComponent', - 'prop', - ); - expect(error).toBe(null); -} - -describe('ReactLink', () => { - it('should fail if the argument does not implement the Link API', () => { - typeCheckFail( - LinkPropTypes.link(React.PropTypes.any), - {}, - 'The prop `testProp.value` is marked as required in `testComponent`, ' + - 'but its value is `undefined`.' - ); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.any), - {value: 123}, - 'The prop `testProp.requestChange` is marked as required in ' + - '`testComponent`, but its value is `undefined`.' - ); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.any), - {requestChange: emptyFunction}, - 'The prop `testProp.value` is marked as required in `testComponent`, ' + - 'but its value is `undefined`.' - ); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.any), - {value: null, requestChange: null}, - 'The prop `testProp.value` is marked as required in `testComponent`, ' + - 'but its value is `null`.' - ); - }); - - it('should allow valid links even if no type was specified', () => { - typeCheckPass( - LinkPropTypes.link(), - {value: 42, requestChange: emptyFunction} - ); - typeCheckPass( - LinkPropTypes.link(), - {value: {}, requestChange: emptyFunction, - }); - }); - - it('should allow no link to be passed at all', () => { - typeCheckPass( - LinkPropTypes.link(React.PropTypes.string), - undefined - ); - }); - - it('should allow valid links with correct value format', () => { - typeCheckPass( - LinkPropTypes.link(React.PropTypes.any), - {value: 42, requestChange: emptyFunction} - ); - typeCheckPass( - LinkPropTypes.link(React.PropTypes.number), - {value: 42, requestChange: emptyFunction} - ); - typeCheckPass( - LinkPropTypes.link(React.PropTypes.node), - {value: 42, requestChange: emptyFunction} - ); - }); - - it('should fail if the link`s value type does not match', () => { - typeCheckFail( - LinkPropTypes.link(React.PropTypes.string), - {value: 123, requestChange: emptyFunction}, - 'Invalid prop `testProp.value` of type `number` supplied to `testComponent`,' + - ' expected `string`.' - ); - }); - - it('should be implicitly optional and not warn without values', () => { - typeCheckPass(LinkPropTypes.link(), null); - typeCheckPass(LinkPropTypes.link(), undefined); - typeCheckPass(LinkPropTypes.link(React.PropTypes.string), null); - typeCheckPass(LinkPropTypes.link(React.PropTypes.string), undefined); - }); - - it('should warn for missing required values', () => { - var specifiedButIsNullMsg = 'The prop `testProp` is marked as required ' + - 'in `testComponent`, but its value is `null`.'; - typeCheckFail(LinkPropTypes.link().isRequired, null, specifiedButIsNullMsg); - typeCheckFail(LinkPropTypes.link().isRequired, undefined, requiredMessage); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.string).isRequired, - null, - specifiedButIsNullMsg - ); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.string).isRequired, - undefined, - requiredMessage - ); - }); - - it('should be compatible with React.PropTypes.oneOfType', () => { - typeCheckPass( - React.PropTypes.oneOfType([LinkPropTypes.link(React.PropTypes.number)]), - {value: 123, requestChange: emptyFunction} - ); - typeCheckFail( - React.PropTypes.oneOfType([LinkPropTypes.link(React.PropTypes.number)]), - 123, - invalidMessage - ); - typeCheckPass( - LinkPropTypes.link(React.PropTypes.oneOfType([React.PropTypes.number])), - {value: 123, requestChange: emptyFunction} - ); - typeCheckFail( - LinkPropTypes.link(React.PropTypes.oneOfType([React.PropTypes.number])), - {value: 'imastring', requestChange: emptyFunction}, - 'Invalid prop `testProp.value` supplied to `testComponent`.' - ); - }); -}); diff --git a/src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js b/src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js index ef0937a7fc5..5f409cddb37 100644 --- a/src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js +++ b/src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js @@ -26,9 +26,7 @@ if (__DEV__) { autoFocus: true, defaultValue: true, - valueLink: true, defaultChecked: true, - checkedLink: true, innerHTML: true, suppressContentEditableWarning: true, onFocusIn: true, diff --git a/src/renderers/dom/shared/utils/LinkedValueUtils.js b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js similarity index 53% rename from src/renderers/dom/shared/utils/LinkedValueUtils.js rename to src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js index c2143827ad1..9d83c6a8882 100644 --- a/src/renderers/dom/shared/utils/LinkedValueUtils.js +++ b/src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js @@ -6,7 +6,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule LinkedValueUtils + * @providesModule ReactControlledValuePropTypes */ 'use strict'; @@ -14,7 +14,6 @@ var React = require('React'); var getComponentName = require('getComponentName'); -var invariant = require('invariant'); var warning = require('warning'); var hasReadOnlyValue = { @@ -27,32 +26,6 @@ var hasReadOnlyValue = { 'submit': true, }; -function _assertSingleLink(inputProps) { - invariant( - inputProps.checkedLink == null || inputProps.valueLink == null, - 'Cannot provide a checkedLink and a valueLink. If you want to use ' + - 'checkedLink, you probably don\'t want to use valueLink and vice versa.' - ); -} -function _assertValueLink(inputProps) { - _assertSingleLink(inputProps); - invariant( - inputProps.value == null && inputProps.onChange == null, - 'Cannot provide a valueLink and a value or onChange event. If you want ' + - 'to use value or onChange, you probably don\'t want to use valueLink.' - ); -} - -function _assertCheckedLink(inputProps) { - _assertSingleLink(inputProps); - invariant( - inputProps.checked == null && inputProps.onChange == null, - 'Cannot provide a checkedLink and a checked property or onChange event. ' + - 'If you want to use checked or onChange, you probably don\'t want to ' + - 'use checkedLink' - ); -} - var propTypes = { value: function(props, propName, componentName) { if (!props[propName] || @@ -101,7 +74,7 @@ function getDeclarationErrorAddendum(owner) { * Provide a linked `value` attribute for controlled forms. You should not use * this outside of the ReactDOM controlled form components. */ -var LinkedValueUtils = { +var ReactControlledValuePropTypes = { checkPropTypes: function(tagName, props, owner) { for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { @@ -122,47 +95,6 @@ var LinkedValueUtils = { } } }, - - /** - * @param {object} inputProps Props for form component - * @return {*} current value of the input either from value prop or link. - */ - getValue: function(inputProps) { - if (inputProps.valueLink) { - _assertValueLink(inputProps); - return inputProps.valueLink.value; - } - return inputProps.value; - }, - - /** - * @param {object} inputProps Props for form component - * @return {*} current checked status of the input either from checked prop - * or link. - */ - getChecked: function(inputProps) { - if (inputProps.checkedLink) { - _assertCheckedLink(inputProps); - return inputProps.checkedLink.value; - } - return inputProps.checked; - }, - - /** - * @param {object} inputProps Props for form component - * @param {SyntheticEvent} event change event to handle - */ - executeOnChange: function(inputProps, event) { - if (inputProps.valueLink) { - _assertValueLink(inputProps); - return inputProps.valueLink.requestChange(event.target.value); - } else if (inputProps.checkedLink) { - _assertCheckedLink(inputProps); - return inputProps.checkedLink.requestChange(event.target.checked); - } else if (inputProps.onChange) { - return inputProps.onChange.call(undefined, event); - } - }, }; -module.exports = LinkedValueUtils; +module.exports = ReactControlledValuePropTypes; diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js index a09d63b0608..6e76c795e65 100644 --- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js +++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMInput-test.js @@ -19,7 +19,6 @@ describe('ReactDOMInput', () => { var ReactDOM; var ReactDOMServer; var ReactDOMFeatureFlags; - var ReactLink; var ReactTestUtils; var inputValueTracking; @@ -36,7 +35,6 @@ describe('ReactDOMInput', () => { ReactDOM = require('ReactDOM'); ReactDOMServer = require('ReactDOMServer'); ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); - ReactLink = require('ReactLink'); ReactTestUtils = require('ReactTestUtils'); inputValueTracking = require('inputValueTracking'); spyOn(console, 'error'); @@ -373,39 +371,6 @@ describe('ReactDOMInput', () => { expect(cNode.checked).toBe(true); }); - it('should support ReactLink', () => { - var link = new ReactLink('yolo', jest.fn()); - var instance = ; - - instance = ReactTestUtils.renderIntoDocument(instance); - - expect(ReactDOM.findDOMNode(instance).value).toBe('yolo'); - expect(link.value).toBe('yolo'); - expect(link.requestChange.mock.calls.length).toBe(0); - - ReactDOM.findDOMNode(instance).value = 'test'; - ReactTestUtils.Simulate.change(ReactDOM.findDOMNode(instance)); - - expect(link.requestChange.mock.calls.length).toBe(1); - expect(link.requestChange.mock.calls[0][0]).toEqual('test'); - }); - - it('should warn with value and no onChange handler', () => { - var link = new ReactLink('yolo', jest.fn()); - ReactTestUtils.renderIntoDocument(); - expect(console.error.calls.count()).toBe(1); - expect(console.error.calls.argsFor(0)[0]).toContain( - '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.' - ); - - ReactTestUtils.renderIntoDocument( - - ); - expect(console.error.calls.count()).toBe(1); - ReactTestUtils.renderIntoDocument(); - expect(console.error.calls.count()).toBe(2); - }); - it('should warn with value and no onChange handler and readOnly specified', () => { ReactTestUtils.renderIntoDocument( @@ -429,71 +394,6 @@ describe('ReactDOMInput', () => { ReactTestUtils.Simulate.change(instance); }); - it('should throw if both value and valueLink are provided', () => { - var node = document.createElement('div'); - var link = new ReactLink('yolo', jest.fn()); - var instance = ; - - expect(() => ReactDOM.render(instance, node)).not.toThrow(); - - instance = - ; - expect(() => ReactDOM.render(instance, node)).toThrow(); - - instance = ; - expect(() => ReactDOM.render(instance, node)).toThrow(); - - }); - - it('should support checkedLink', () => { - var link = new ReactLink(true, jest.fn()); - var instance = ; - - instance = ReactTestUtils.renderIntoDocument(instance); - - expect(ReactDOM.findDOMNode(instance).checked).toBe(true); - expect(link.value).toBe(true); - expect(link.requestChange.mock.calls.length).toBe(0); - - ReactDOM.findDOMNode(instance).checked = false; - ReactTestUtils.Simulate.change(ReactDOM.findDOMNode(instance)); - - expect(link.requestChange.mock.calls.length).toBe(1); - expect(link.requestChange.mock.calls[0][0]).toEqual(false); - }); - - it('should warn with checked and no onChange handler', () => { - var node = document.createElement('div'); - var link = new ReactLink(true, jest.fn()); - ReactDOM.render(, node); - expect(console.error.calls.count()).toBe(1); - expect(console.error.calls.argsFor(0)[0]).toContain( - '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.' - ); - - ReactTestUtils.renderIntoDocument( - - ); - expect(console.error.calls.count()).toBe(1); - - ReactTestUtils.renderIntoDocument( - - ); - expect(console.error.calls.count()).toBe(1); - - ReactTestUtils.renderIntoDocument(); - expect(console.error.calls.count()).toBe(2); - }); - it('should warn with checked and no onChange handler with readOnly specified', () => { ReactTestUtils.renderIntoDocument( @@ -506,28 +406,6 @@ describe('ReactDOMInput', () => { expect(console.error.calls.count()).toBe(1); }); - it('should throw if both checked and checkedLink are provided', () => { - var node = document.createElement('div'); - var link = new ReactLink(true, jest.fn()); - var instance = ; - - expect(() => ReactDOM.render(instance, node)).not.toThrow(); - - instance = - ; - expect(() => ReactDOM.render(instance, node)).toThrow(); - - instance = - ; - expect(() => ReactDOM.render(instance, node)).toThrow(); - - }); - it('should update defaultValue to empty string', () => { var container = document.createElement('div'); ReactDOM.render(, container); @@ -535,21 +413,6 @@ describe('ReactDOMInput', () => { expect(container.firstChild.defaultValue).toBe(''); }); - it('should throw if both checkedLink and valueLink are provided', () => { - var node = document.createElement('div'); - var link = new ReactLink(true, jest.fn()); - var instance = ; - - expect(() => ReactDOM.render(instance, node)).not.toThrow(); - - instance = ; - expect(() => ReactDOM.render(instance, node)).not.toThrow(); - - instance = - ; - expect(() => ReactDOM.render(instance, node)).toThrow(); - }); - it('should warn if value is null', () => { ReactTestUtils.renderIntoDocument(); expect(console.error.calls.argsFor(0)[0]).toContain( diff --git a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMSelect-test.js b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMSelect-test.js index 816d2b57836..78495399037 100644 --- a/src/renderers/dom/shared/wrappers/__tests__/ReactDOMSelect-test.js +++ b/src/renderers/dom/shared/wrappers/__tests__/ReactDOMSelect-test.js @@ -16,7 +16,6 @@ describe('ReactDOMSelect', () => { var React; var ReactDOM; var ReactDOMServer; - var ReactLink; var ReactTestUtils; var noop = function() {}; @@ -25,7 +24,6 @@ describe('ReactDOMSelect', () => { React = require('React'); ReactDOM = require('ReactDOM'); ReactDOMServer = require('ReactDOMServer'); - ReactLink = require('ReactLink'); ReactTestUtils = require('ReactTestUtils'); }); @@ -347,40 +345,6 @@ describe('ReactDOMSelect', () => { expect(node.options[2].selected).toBe(true); // gorilla }); - it('should support ReactLink', () => { - var link = new ReactLink('giraffe', jest.fn()); - var stub = - ; - - spyOn(console, 'error'); - - stub = ReactTestUtils.renderIntoDocument(stub); - - expect(console.error.calls.count()).toBe(1); - expect(console.error.calls.argsFor(0)[0]).toContain( - '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.' - ); - - var node = ReactDOM.findDOMNode(stub); - - expect(node.options[0].selected).toBe(false); // monkey - expect(node.options[1].selected).toBe(true); // giraffe - expect(node.options[2].selected).toBe(false); // gorilla - expect(link.requestChange.mock.calls.length).toBe(0); - - node.options[1].selected = false; - node.options[2].selected = true; - ReactTestUtils.Simulate.change(node); - - expect(link.requestChange.mock.calls.length).toBe(1); - expect(link.requestChange.mock.calls[0][0]).toEqual('gorilla'); - - }); - it('should support server-side rendering', () => { var stub =