From 8fa20bb467bd2bd6428007b0ffe7caf55164bd3f Mon Sep 17 00:00:00 2001 From: Nathan Hunzaker Date: Sat, 19 Nov 2016 10:38:42 -0500 Subject: [PATCH] Move ReactDOMFactories into separate package - Update examples to no longer use React.DOM - Add package and documentation entries for react-addons-dom-factories - Update dom-factories readme - Set up proxy to intercept React.DOM usage - Update ReactDOM children tests to use createElement - Add more specific warning assertion for React DOM factories - Do not use expectDev in ReactDOMFactories tests --- docs/docs/addons.md | 1 + packages/react-dom-factories/README.md | 20 ++++++++++ packages/react-dom-factories/index.js | 3 ++ packages/react-dom-factories/package.json | 25 ++++++++++++ scripts/fiber/tests-passing.txt | 5 ++- .../element => addons}/ReactDOMFactories.js | 1 - .../__tests__/ReactDOMFactories-test.js | 39 +++++++++++++++++++ src/isomorphic/React.js | 21 ++++++++++ .../element/__tests__/ReactElement-test.js | 10 +++-- .../dom/shared/__tests__/ReactDOM-test.js | 11 +----- .../__tests__/ReactDOMComponent-test.js | 3 +- 11 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 packages/react-dom-factories/README.md create mode 100644 packages/react-dom-factories/index.js create mode 100644 packages/react-dom-factories/package.json rename src/{isomorphic/classic/element => addons}/ReactDOMFactories.js (99%) create mode 100644 src/addons/__tests__/ReactDOMFactories-test.js diff --git a/docs/docs/addons.md b/docs/docs/addons.md index d0f6a770b8ec..b9575b3fa38f 100644 --- a/docs/docs/addons.md +++ b/docs/docs/addons.md @@ -23,6 +23,7 @@ The add-ons below are considered legacy and their use is discouraged. - [`PureRenderMixin`](pure-render-mixin.html). Use [`React.PureComponent`](/react/docs/react-api.html#react.purecomponent) instead. - [`shallowCompare`](shallow-compare.html), a helper function that performs a shallow comparison for props and state in a component to decide if a component should update. - [`update`](update.html). Use [`kolodny/immutability-helper`](https://github.com/kolodny/immutability-helper) instead. +- [`ReactDOMFactories`](dom-factories.html), pre-configured DOM factories to make React easier to use without JSX. ### Deprecated Add-ons diff --git a/packages/react-dom-factories/README.md b/packages/react-dom-factories/README.md new file mode 100644 index 000000000000..20b02d5c2683 --- /dev/null +++ b/packages/react-dom-factories/README.md @@ -0,0 +1,20 @@ +# `react-addons-dom-factories` + +> Note: +> `ReactDOMFactories` is a legacy add-on. Consider using +> `React.createFactory` or JSX instead. + +Prior to version 16.0.0, React maintained a whitelist of +pre-configured DOM factories. These predefined factories have been +moved to the `react-addons-dom-factories` library. + +## Example + +```javascript +import ReactDOM from 'react-dom'; +import DOM from 'react-addons-dom-factories'; // ES6 + +const greeting = DOM.div({ className: 'greeting' }, DOM.p(null, 'Hello, world!')); + +ReactDOM.render(greeting, document.getElementById('app')) +``` diff --git a/packages/react-dom-factories/index.js b/packages/react-dom-factories/index.js new file mode 100644 index 000000000000..0a5ad7f3529f --- /dev/null +++ b/packages/react-dom-factories/index.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./lib/ReactDOMFactories'); diff --git a/packages/react-dom-factories/package.json b/packages/react-dom-factories/package.json new file mode 100644 index 000000000000..4b3815c8b1f6 --- /dev/null +++ b/packages/react-dom-factories/package.json @@ -0,0 +1,25 @@ +{ + "name": "react-dom-factories", + "version": "16.0.0-alpha", + "description": "React package for DOM factory methods.", + "main": "index.js", + "repository": "facebook/react", + "keywords": [ + "react" + ], + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/facebook/react/issues" + }, + "homepage": "https://facebook.github.io/react/", + "peerDependencies": { + "react": "^16.0.0-alpha" + }, + "files": [ + "LICENSE", + "PATENTS", + "README.md", + "index.js", + "lib/" + ] +} diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 470fee62074a..eb73673aebef 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -42,6 +42,10 @@ scripts/shared/__tests__/evalToString-test.js * should support string concat (`+`) * should throw when it finds other types +src/addons/__tests__/ReactDOMFactories-test.js +* allow factories to be called without warnings +* warns once when accessing React.DOM methods + src/isomorphic/__tests__/React-test.js * should log a deprecation warning once when using React.createMixin * should warn once when attempting to access React.createClass @@ -835,7 +839,6 @@ src/renderers/dom/shared/__tests__/ReactDOM-test.js * should allow children to be passed as an argument * should overwrite props.children with children argument * should purge the DOM cache when removing nodes -* allow React.DOM factories to be called without warnings * throws in render() if the mount callback is not a function * throws in render() if the update callback is not a function * preserves focus diff --git a/src/isomorphic/classic/element/ReactDOMFactories.js b/src/addons/ReactDOMFactories.js similarity index 99% rename from src/isomorphic/classic/element/ReactDOMFactories.js rename to src/addons/ReactDOMFactories.js index c6ee9fc5d174..f1f82c3a0152 100644 --- a/src/isomorphic/classic/element/ReactDOMFactories.js +++ b/src/addons/ReactDOMFactories.js @@ -26,7 +26,6 @@ if (__DEV__) { /** * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes. - * This is also accessible via `React.DOM`. * * @public */ diff --git a/src/addons/__tests__/ReactDOMFactories-test.js b/src/addons/__tests__/ReactDOMFactories-test.js new file mode 100644 index 000000000000..b4a7a78ceda5 --- /dev/null +++ b/src/addons/__tests__/ReactDOMFactories-test.js @@ -0,0 +1,39 @@ +/** + * 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 React = require('React'); +var {div} = require('ReactDOMFactories'); + +describe('ReactDOMFactories', () => { + it('allow factories to be called without warnings', () => { + spyOn(console, 'error'); + var element = div(); + expect(element.type).toBe('div'); + expect(console.error).not.toHaveBeenCalled(); + }); + + it('warns once when accessing React.DOM methods', () => { + spyOn(console, 'error'); + + var a = React.DOM.a(); + var p = React.DOM.p(); + + expect(a.type).toBe('a'); + expect(p.type).toBe('p'); + + expect(console.error).toHaveBeenCalledTimes(1); + expect(console.error.calls.first().args[0]).toContain( + 'Warning: Accessing factories like React.DOM.a has been deprecated', + ); + }); +}); diff --git a/src/isomorphic/React.js b/src/isomorphic/React.js index eebe7b9b556a..a0ff8930ab3b 100644 --- a/src/isomorphic/React.js +++ b/src/isomorphic/React.js @@ -146,6 +146,27 @@ if (__DEV__) { }, }); } + + // React.DOM factories are deprecated. Wrap these methods so that + // invocations of the React.DOM namespace and alert users to switch + // to the `react-addons-dom-factories` package. + React.DOM = {}; + var warnedForFactories = false; + Object.keys(ReactDOMFactories).forEach(function(factory) { + React.DOM[factory] = function(...args) { + if (!warnedForFactories) { + warning( + false, + 'Accessing factories like React.DOM.%s has been deprecated ' + + 'and will be removed in the future. Use the ' + + 'react-addons-dom-factories package instead.', + factory, + ); + warnedForFactories = true; + } + return ReactDOMFactories[factory](...args); + }; + }); } module.exports = React; diff --git a/src/isomorphic/classic/element/__tests__/ReactElement-test.js b/src/isomorphic/classic/element/__tests__/ReactElement-test.js index 0db69a0c9abd..3d6f7b9efc3e 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElement-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElement-test.js @@ -322,7 +322,7 @@ describe('ReactElement', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - expect(React.isValidElement(React.DOM.div)).toEqual(false); + expect(React.isValidElement(React.createFactory('div'))).toEqual(false); expect(React.isValidElement(Component)).toEqual(false); expect(React.isValidElement({type: 'div', props: {}})).toEqual(false); @@ -465,7 +465,7 @@ describe('ReactElement', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - expect(React.isValidElement(React.DOM.div)).toEqual(false); + expect(React.isValidElement(React.createFactory('div'))).toEqual(false); expect(React.isValidElement(Component)).toEqual(false); expect(React.isValidElement({type: 'div', props: {}})).toEqual(false); @@ -526,7 +526,8 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => { var childFactory = React.createFactory(Child); class Parent extends React.Component { render() { - return React.DOM.div( + return React.createElement( + 'div', {}, childFactory({ref: 'child', foo: 'foo value'}, 'children value'), ); @@ -561,7 +562,8 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => { beforeEach(() => { class Parent extends React.Component { render() { - return React.DOM.div( + return React.createElement( + 'div', {}, React.createElement( Child, diff --git a/src/renderers/dom/shared/__tests__/ReactDOM-test.js b/src/renderers/dom/shared/__tests__/ReactDOM-test.js index cedcfbd34ac3..1f5455883393 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOM-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOM-test.js @@ -53,7 +53,7 @@ describe('ReactDOM', () => { it('should allow children to be passed as an argument', () => { var argDiv = ReactTestUtils.renderIntoDocument( - React.DOM.div(null, 'child'), + React.createElement('div', null, 'child'), ); var argNode = ReactDOM.findDOMNode(argDiv); expect(argNode.innerHTML).toBe('child'); @@ -61,7 +61,7 @@ describe('ReactDOM', () => { it('should overwrite props.children with children argument', () => { var conflictDiv = ReactTestUtils.renderIntoDocument( - React.DOM.div({children: 'fakechild'}, 'child'), + React.createElement('div', {children: 'fakechild'}, 'child'), ); var conflictNode = ReactDOM.findDOMNode(conflictDiv); expect(conflictNode.innerHTML).toBe('child'); @@ -110,13 +110,6 @@ describe('ReactDOM', () => { expect(dog.className).toBe('bigdog'); }); - it('allow React.DOM factories to be called without warnings', () => { - spyOn(console, 'error'); - var element = React.DOM.div(); - expect(element.type).toBe('div'); - expectDev(console.error.calls.count()).toBe(0); - }); - it('throws in render() if the mount callback is not a function', () => { spyOn(console, 'error'); diff --git a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js index 6468f45b9a1f..279e72e0f118 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js @@ -1193,7 +1193,8 @@ describe('ReactDOMComponent', () => { it('should properly escape text content and attributes values', () => { expect( ReactDOMServer.renderToStaticMarkup( - React.DOM.div( + React.createElement( + 'div', { title: '\'"<>&', style: {