Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create react-addons-dom-factories package #8356

Merged
merged 1 commit into from
Apr 24, 2017

Conversation

nhunzaker
Copy link
Contributor

@nhunzaker nhunzaker commented Nov 19, 2016

Moves React DOM factories out of React, makes new react-addons-dom-factories package. Adds basic documentation for new addon.

I hope this is most of the legwork for #6169.

Sort of tangental, but this reduces React down to 5.3kb gzipped. Pretty neat :)

screen shot 2016-11-20 at 12 54 27 pm

@@ -891,7 +894,6 @@ src/renderers/dom/stack/client/__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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did some furniture moving of the factory tests, which failed CI. So I updated the test recording using:

scripts/fiber/record-tests --track-facts

Did I do this correctly?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need --track-facts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I figured that out later, when I hit a permissions issue not having write access to the repo. Everything else worked perfectly.

@gaearon
Copy link
Collaborator

gaearon commented Nov 21, 2016

We can't do this in a single pass. As a first step we should create the new package and add a deprecation warning when you access React.DOM which points to the package. Then we can release this in a minor and do another pass where we actually remove React.DOM.

@nhunzaker
Copy link
Contributor Author

Ah. Makes sense. I'll bring it back.

@nhunzaker
Copy link
Contributor Author

Done, I've set up a Proxy to intercept React.DOM when available:

screen shot 2016-11-21 at 8 56 45 pm

@nhunzaker
Copy link
Contributor Author

Sort of tangental, but this was my first pseudo-production use of a Proxy. What a cool API. It's a bummer Proxy.revocable isn't quite as well supported.

@nhunzaker nhunzaker force-pushed the react-dom-factories-package branch 2 times, most recently from add4fc2 to da03cba Compare January 23, 2017 13:54
@gaearon gaearon self-assigned this Jan 23, 2017
@nhunzaker
Copy link
Contributor Author

I've upstreamed it with master, fixed some tests, and re-recorded the fiber output.

I don't want this PR to be too much of a thorn in your side. I'll periodically keep it up to date with master so it's not difficult to update whenever it makes sense to evaluate it.

expect(a.type).toBe('a');
expect(p.type).toBe('p');

expectDev(console.error.calls.count()).toBe(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an assertion on the content of the warning? It's not a big deal, but I like to make sure the tests are checking for the correct warning, not just any warning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure can.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, though it feels a bit cumbersome. Do you know of a better way to make this check?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the way you did it is how it is done throughout the React tests.

@nhunzaker
Copy link
Contributor Author

Ack! those double quotes get me every time. Fixed.

@nhunzaker
Copy link
Contributor Author

Conflicts resolved. Anything else I can do here to help move this along?

@aweary aweary mentioned this pull request Apr 10, 2017
49 tasks
@flarnie flarnie added this to the 15.6 milestone Apr 13, 2017
title: DOM Factories
permalink: docs/dom-factories.html
layout: docs
category: Add-Ons
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We removed the 'Add-Ons' section of the docs from the main navigation when we deprecated most of them in v15.5. (#9359) I think it's worth having this documentation - maybe we could put it in the README for the new separate module?

// accesses to the React.DOM namespace and alert users to switch to
// the `react-addons-dom-factories` package.
if (typeof Proxy === 'function') {
var hasWarnedOfFactories = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this use of a Proxy. I'm wondering though about the fact that, according to MDN, Proxy is not yet supported in IE. To also show this warning in IE, we may want to switch and add the warning in the copy of ReactDOMFactories that remains in React. We could do that in a follow-up PR though.

Copy link
Contributor

@aweary aweary Apr 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should instead use Object.defineProperty to define getters for each method, so we don't have to rely on Proxy at all and split up the logic for these warnings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Object.defineProperty could be handy.
With Object.defineProperty it might look like this:

if (__DEV__) {
  // React.DOM factories are deprecated. ...(rest of comment)
  var hasWarnedOfFactories = false;
  var DOMFactoryMethodNameList = ['a', 'abbr', 'address', ... 'text', 'tspan'];
  DOMFactoryMethodNameList.forEach((method) => {
    React.DOM = Object.defineProperty(React.DOM, method, {
      get: function() {
        if (!hasWarnedOfFactories) {
          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.',
            method
          );

          hasWarnedOfFactories = true;
        }
        return React.DOM[method];
      },
    });
  });

  }

Unless there is a way to define a generic 'get' for all object attributes with Object.defineProperty?

If not then it seems just as easy to do without the Object.defineProperty call I think, something like this;

if (__DEV__) {
  // React.DOM factories are deprecated. ...(rest of comment)
  var hasWarnedOfFactories = false;
  var DOMFactoryMethodNameList = ['a', 'abbr', 'address', ... 'text', 'tspan'];
  DOMFactoryMethodNameList.forEach((method) => {
    var wrappedMethod = React.DOM[method];
    React.DOM[method] = function() {
      if (!hasWarnedOfFactories) {
        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.',
          method
        );

        hasWarnedOfFactories = true;
      }
      return wrappedMethod.apply(null, Array.prototype.slice.call(arguments));
    });
  });

  }

Both of these instantiate an extra wrapper function for every factory method, which is annoying. I figure a follow-up PR, either by me or someone else, can come up with a good approach.

Copy link
Contributor

@aweary aweary Apr 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could simply it further by using a for ... in loop over ReactDOMFactories!

if (__DEV__) {
  var warnedForFactories = false;
  for (var factory in ReactDOMFactories) {
    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);
    }
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, 👍

@flarnie flarnie changed the base branch from master to 15.6-dev April 18, 2017 22:36
@flarnie flarnie changed the base branch from 15.6-dev to master April 18, 2017 22:42
@flarnie
Copy link
Contributor

flarnie commented Apr 18, 2017

Thanks for your patience on this PR @nhunzaker! We plan on merging it both into master, which will be v16.0, and the v15.6-dev branch. Unfortunately the build process on master has changed quite a bit.

I think the simplest way is this:

  1. I (or you if you have time first) will cherry-pick the commits from this PR into a new PR to make against v15.6-dev branch. That should be pretty easy to merge with minimal updates.
  2. I (or you if you have time first) can make a commit on this PR updating it to work with the build process on master, and we will then be able to merge it there.

Hope that makes sense. :)

@nhunzaker
Copy link
Contributor Author

@flarnie Sorry for the late response. All of this makes a ton of sense. I should be able to resolve the feedback later today.

flarnie added a commit to flarnie/react-codemod that referenced this pull request Apr 20, 2017
Since we are deprecating the 'React.DOM.*' factories,[1] we want to
provide a codemod so that it's easier for folks to upgrade their code.

This will include an option to use 'React.createFactory' instead of
'React.createElement' in case there is a use case where that is
preferred.

There is one use of `React.DOM.*` that I have seen which is not covered
here - sometimes it has mistakenly been used for Flow typing. In the
cases I have found it is not proper syntax and doesn't seem like
something we should cover with this codemod.

[1]: facebook/react#9398
and facebook/react#8356
@bvaughn bvaughn mentioned this pull request Aug 1, 2017
toptaldev92 pushed a commit to toptaldev92/react-codemod that referenced this pull request Jul 28, 2021
Since we are deprecating the 'React.DOM.*' factories,[1] we want to
provide a codemod so that it's easier for folks to upgrade their code.

This will include an option to use 'React.createFactory' instead of
'React.createElement' in case there is a use case where that is
preferred.

There is one use of `React.DOM.*` that I have seen which is not covered
here - sometimes it has mistakenly been used for Flow typing. In the
cases I have found it is not proper syntax and doesn't seem like
something we should cover with this codemod.

[1]: facebook/react#9398
and facebook/react#8356
superbuddyy pushed a commit to superbuddyy/react-codemod that referenced this pull request Aug 9, 2022
Since we are deprecating the 'React.DOM.*' factories,[1] we want to
provide a codemod so that it's easier for folks to upgrade their code.

This will include an option to use 'React.createFactory' instead of
'React.createElement' in case there is a use case where that is
preferred.

There is one use of `React.DOM.*` that I have seen which is not covered
here - sometimes it has mistakenly been used for Flow typing. In the
cases I have found it is not proper syntax and doesn't seem like
something we should cover with this codemod.

[1]: facebook/react#9398
and facebook/react#8356
cookieranger pushed a commit to cookieranger/react-codemod that referenced this pull request Jan 16, 2023
Since we are deprecating the 'React.DOM.*' factories,[1] we want to
provide a codemod so that it's easier for folks to upgrade their code.

This will include an option to use 'React.createFactory' instead of
'React.createElement' in case there is a use case where that is
preferred.

There is one use of `React.DOM.*` that I have seen which is not covered
here - sometimes it has mistakenly been used for Flow typing. In the
cases I have found it is not proper syntax and doesn't seem like
something we should cover with this codemod.

[1]: facebook/react#9398
and facebook/react#8356
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants