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

Warning: This JSX uses a plain function. Only React components are valid in React's JSX transform. #2436

Closed
TrySpace opened this issue Oct 30, 2014 · 22 comments

Comments

@TrySpace
Copy link

I just updated to React 0.12.0, and now a mass of warnings flood my console:

  Warning: This JSX uses a plain function. Only React components are valid in React's JSX transform. 

It seems to have to do with which elements I'm using, and the only thing that seems to fix it is by re-building imported ( var Button = React.createFactory(require('./button')) ) like:

    var ButtonComponent = React.createClass({
      render: function() {
        return Button({ });
      }
    });

But I think that's rather unnecessary and think this is not the purpose of the update, and I thought that .createFactory would be enough for imported components, but it's not. I do use browserify if that helps.

So I can create new elements fine with createElement for example, without warnings, but when I try to RE-USE elements, which is exactly why we all want to use React... It warns me..

In a few cases it gave me the specific element name that wasn't right, but that was fixed by putting .createFactory before require()..

I am working in jsx, which is auto compiled through gulp-jsx, I think that's updated (2.0.0), because I don't need the @jsx tags anymore..

The warning does not give me anything to trace as well, but I pinpointed it to happening in each render method of components (elements?) that re-use either imported ones, or others in the same file/scope/module.
So like:

 render: function(){
      return(
         <div>
           <h2>This works fine </h2>
           <Button title="Gives warning, but not when removed" />
        </div>
      )
     }

Anyone can say what I'm missing here? It can't be the purpose, to be forced to give your imported elements a different name (because assigning the same Variable name to the createClass as the require'd one will throw the same warning.)

What does it mean with 'components are valid', it is valid, it is React.

I can't find that much about what is meant with 'Plain functions' it is mentioned once in one of the blog updates. I tried making my existing components, through the new methods, but warnings persist.

What is exactly needed (barebones) to avoid these warnings, and will it ever break my app in new updates? I came from I 0.11, where everything worked fine.. So the transition should be that big.. I must be missing some essential thing here...

@syranide
Copy link
Contributor

If you're using JSX you must not use React.createFactory or React.createElement and then use the result as a tag in JSX, you should only use the class itself, i.e the value of React.createClass.

I'm not intimately familiar with the tests for the various warnings, but it explicitly says "Warning: This JSX uses a plain function. Only React components are valid in React's JSX transform.". I.e. you're doing:

function Foo() {
  ...
}

return <Foo />;

Which is not valid anymore.

@zpao
Copy link
Member

zpao commented Oct 31, 2014

One place we're seeing people get tripped up by this is tooling. They are upgrading React without upgrading the JSX transform pipeline. If you are using react-tools directly, reactify, or any other library doing the transform, it must also be updated. You said you updated gulp-react but l I would double check that. Inserting createFactory calls would only fix JSX uses if you are still transforming with the old pipeline.

An easy way to check is look at compiled output. If createElement is nowhere to be found, then you are still using the old JSX transform.

@jasonkuhrt
Copy link

I'm seeing this error and am not using JSX or grunt. I'm building duo which should have no affect on this issue... I don't have any ideas right now.

@jasonkuhrt
Copy link

I spoke too fast. I had .createFactor being used twice accidentally. Never mind!

@TrySpace
Copy link
Author

TrySpace commented Nov 7, 2014

@zpao : the package.json says: "react-tools": "^0.12.0" so it should be fine. And I do see createElement in the browerified source.

So the error must come from something else.

So I've made a new project, and now get: Warning: Something is calling a React component directly. Use a factory or JSX instead. See: http://fb.me/react-legacyfactory Now I do use JSX to write it, but the code in my browser is pure js ofcourse, after compilation.

I'm doing everthing https://gist.github.com/sebmarkbage/ae327f2eda03bf165261 says, and I'm not even importing components, just a few mixins and they won't accept createFactory.

And I use JSX to write everything, so in theory, I shouldn't be even seeing this error, according to the update logs (which is beginning to become a bit of a hassle to read through, as the docs are just changed, and no refferal to 'old ways' are pointed out, or no real migration examples or 1 by 1 comparisons... )

@syranide
Copy link
Contributor

syranide commented Nov 7, 2014

@TrySpace Please post your code/repro.

@TrySpace
Copy link
Author

TrySpace commented Nov 7, 2014

@syranide : I'm not, I'm just working in pure jsx for the component, the only time it happens, when I use another component in my render-return. This component comes from either:

  • require() And I did put React.createFactory() around it, althought this should not be necessary when using jsx
  • the same file/scope ( and tried to wrap the createClass around a React.createFactory() but no difference

Can't post my repo because it is private, but the code is pretty simple:

 var React = require('react/addons');
 var Button= React.createFactory(require("./button"));

 // Arrow
 var Something = React.createClass({  
   render: function(){
     return(
        <div>
          <h2> This works fine </h2>
          <Button title="This Element gives warning, but not when removed" />
       </div>
     )
    } 
  })
  module.exports = Something;

However, removing the <Button/> or the following does not give the warning:

  var React = require('react/addons');
   var Button= React.createFactory(require("./button"));

 // Arrow
 var Something = React.createClass({  
   render: function(){
      var ButtonComponent = React.createClass({
           render: function() {
          return Button({ });
        }
       });

     return(
        <div>
          <h2> This works fine </h2>
          <ButtonComponent title="I'm fine for some reason" />
       </div>
     )
    } 
  })
  module.exports = Something;

Which is of course, a ridiculous workaround, and not the solution. And really does not explain why the warning was given, because here, I'm not even using a createFactory or anything, and no JSX as well!

@syranide
Copy link
Contributor

syranide commented Nov 7, 2014

@TrySpace You shouldn't use React.createFactory for JSX.

PS. Also, you definitely do not want to create a new ButtonComponent every render.

@doronaviguy
Copy link

refering to the code sample above ,
is this valid ? or the right way for exposing a component using browserify .

module.exports = React.createFactory(Something);

@yocontra
Copy link
Contributor

After 0.12, should components on npm

module.exports = React.createFactory(MyComponent);

or do users of the module have to wrap it in createFactory every time?

It seems like if components export createFactory's then the module can't be used by people who use JSX without spewing these errors to the console, so the solution is for users to always wrap all requires in a createFactory which seems a little tedious IMO. Is this right?

@sophiebits
Copy link
Collaborator

See this blog post – library authors should export unwrapped classes:

http://facebook.github.io/react/blog/2014/10/14/introducing-react-elements.html#anti-pattern-exporting-factories

@TrySpace
Copy link
Author

@contra, that would seem logical to me as well, but apparently we need to import them with a factory, which I think personally is very messy.

require should be require, no wrapping. Sure, it would be easily identifiable as a component (element?) But if you start out and don't know what you're importing, there are other problems you should adress first for your project, like documentation.

@sophiebits
Copy link
Collaborator

I don't think there's anything actionable here so I'm closing – please correct me if I'm wrong.

@TrySpace
Copy link
Author

@spicyj What do you need? I still don't know why these warnings show, as the documentation is not clear

@sophiebits
Copy link
Collaborator

@TrySpace It looks like you're using both createFactory and JSX – is that right? If you're using JSX to specify the elements you shouldn't ever need to call createFactory.

@TrySpace
Copy link
Author

@spicyj, right, I'm sure I had tested that before, but that indeed fixes the warnings, as expected, thanks!

@sophiebits
Copy link
Collaborator

@sebmarkbage Do you want to do an explicit warning when using the output of createFactory with JSX instead of the generic "don't use functions with JSX" warning? Doesn't look like there's a real way to identify them at present but we could always add a ._isReactFactory or something…

@syranide
Copy link
Contributor

@spicyj As it's only for a temporary warning, detecting if .type exists may be enough.

@irvinebroque
Copy link

Is there any way to improve the error message to output which part of the JSX uses a plain function? Understand and support the breaking change, but if possible I'd like to know where the problem is so that I can fix it.

@TrySpace
Copy link
Author

TrySpace commented Dec 4, 2014

Agreed, I fixed all but 1 warnings, somewhere at the beginning. I'm assuming it is the initial React.render, which, as far as I know is not possible to JSX'ify

@syranide
Copy link
Contributor

syranide commented Dec 4, 2014

@TrySpace Sure it is, otherwise just invoke React.createElement(MyClass, ...) manually if you want to avoid JSX there.

@sophiebits
Copy link
Collaborator

@irvinebroque Unfortunately it's not possible for us to print out a better error but you should be able to set a breakpoint at the warning and then inspect the call stack to see what part of your code is causing the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants