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

React-rails with react-select #437

Closed
CostaRico opened this issue Jan 8, 2016 · 24 comments
Closed

React-rails with react-select #437

CostaRico opened this issue Jan 8, 2016 · 24 comments

Comments

@CostaRico
Copy link

I've installed react-select with npm, next in components.js:

//= require_tree ./components

Functions      = require('utils/functions');
_              = require('lodash');
$              = require('jquery');
UserActions = require('./actions/UserActions');
UserStore = require('./stores/UserStore');
Select = require('react-select');

Next, when I use react-select component I see the error "Only a ReactOwner can have refs. You might be adding"

How to install react-select?

@gauravtiwari
Copy link

@CostaRico You are probably adding multiple versions of react source? Please check react-select module and also you are not loading react via Sprockets.

@CostaRico
Copy link
Author

@gauravtiwari I've removed it, now my files looks like:

application.js

//= require jquery
//= require jquery_ujs
//= require react
//= require react_ujs


//= require components

//= require utils/functions
//= require_tree .
//= require bootstrap-sprockets

And components.js

//= require_tree ./components

Functions      = require('utils/functions');
_              = require('lodash');
$              = require('jquery');
UserActions = require('./actions/UserActions');
UserStore = require('./stores/UserStore');
Select2 = require('select2');
Toastr = require('toastr');
Select = require('react-select');

But still the same =(

@CostaRico
Copy link
Author

this is output of
npm ls | grep react

├─┬ [email protected]
├── [email protected]
├─┬ [email protected]
├── [email protected] extraneous
├─┬ [email protected]
│ ├─┬ [email protected]
npm ERR! extraneous: [email protected] /Users/Costa/Frontend/vape-markup/node_modules/select2-browserify
npm ERR! extraneous: [email protected] /Users/Costa/Frontend/vape-markup/node_modules/react-select

@CostaRico
Copy link
Author

I've just created clean rails app, next installed react-reails and react-select and got this error again.

You could try it by yourself https://gitlab.com/CostaRico/test-react-select/

@rmosolgo
Copy link
Member

Thanks for posting that example.

Here's a related issue on react-select: JedWatson/react-select#606 Sounds like most cases is requiring React more than once.

I think I see React being loaded twice in your app, too:

  • Once by Select.js, which is denoted as "main" in react-select's package.json:

    image

    (This copy of React enters the main bundle because of //= require components in application.js)

  • And again by Sprockets, in application.js:

    image

I think you could fix this problem by loading React only once:

  • Copy node_modules/react-select/dist/react-select.js into application/assets/javascripts
  • Replace var Select = require("react-select") with //= require react-select

Maybe you don't want to structure your app that way, but it would test if it's a dependency management problem!

@CostaRico
Copy link
Author

@rmosolgo hello, I've done what u told me, and it seems you are right, but.
Next I faced to error "classes is not a function", so I needed to remove ClassNames dependency from react-select, I did it. Next I realized that react-input-autosize also is dependency and I remove it too, but next I got first error about refs.
So I think it's evil circle.

What do you think would be right way?

  1. try to use react with no react-rails
  2. just don't use react-select (by I'm afraid of other libraries could give the same error)

Thx a lot for your help!

@gauravtiwari
Copy link

@CostaRico the browserify workflow takes care of the dependency management. Sprockets uses a different workflow and for that you have to use different versions of these modules separately. Rails assets https://rails-assets.org/ is one such place to import these libraries and make it work with Sprockets, however since you are using browserify I think it's best to use that.

Also, please require react-select only in places you need it, not globally in component.js. For example: If you have a component - Post, where you have used react-select, require on top of the component like so:

var Select = require('react-select')

and browserify will take care of all the dependencies etc. Same goes for react, autosize and other modules you are using. It makes sense to require them globally only if you are using it everywhere.

Also, use this syntax:

import React from 'react';
import Select from 'react-select';

Check some examples here: https://github.com/JedWatson/react-select/blob/master/examples/src/components/CustomComponents.js

@maximedelpit
Copy link

maximedelpit commented May 6, 2016

Hi there,

I'm facing an issue when loading external react libraries (and react-select specifically). I've not implemented browserify workflow and use Sprockets. I've found on rails-assets.org the gem rails-assets-react-selectbut I don't succeed in using it (same remark for react-charjs).

My application.jsis

//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require jquery-fileupload/basic
//= require jquery-fileupload/vendor/tmpl
//= require react
//= require react_ujs
//= require components
//require sweetalert2
//= require_analytics

//= require_tree .

My components.js is:

//= require js-routes
//= require classnames
//= require LinkedStateMixin
//= require react-dom
//= require react-chartjs
//= require react-select

//= require_tree ./components

When loading my page, I get these errors in my inspector:

Uncaught Error: Cannot find module 'react-dom'

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).warning 

Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

I first supposed that since react-select mention var ReactDom = require('react-dom).DOMthat I had to install the gem from rails-assets. But the error keeps going on.

Any idea of what it can comme from. I probably miss something in the way of importing a react-library.
I could copy the lib in vendor and replace all node syntax (module, require, import, export). But it is what rails-assets gems take care off, isn't it?

What are you recommendation to load react libraries in my rails app using traditionnal asset pipeline?

Thanks for your help,

By the way, thanks for this awesome gem!

@carlows
Copy link

carlows commented Sep 5, 2016

I'm having the exact same issue as @maximedelpit, have you found any workarounds? 😞

@harikumar8984
Copy link

i am facing same issue. Any help would be much appreciated.

@rmosolgo
Copy link
Member

rmosolgo commented Dec 9, 2016

first supposed that since react-select mention var ReactDom = require('react-dom).DOM

react-rails provides this library as ReactDOM, so you can probably make it work with:

var ReactDom = window.ReactDOM

Please reopen or let me know if that doesn't work

@rmosolgo rmosolgo closed this as completed Dec 9, 2016
@reedlaw
Copy link

reedlaw commented Jan 6, 2017

I having trouble with the Sprockets approach. I've tried including var ReactDom = window.ReactDOM but I'm not sure where to put it because it has to come after //= require react-select which is too late. So I'm not sure where to put that line.

@gauravtiwari
Copy link

@reedlaw You can do it like so I guess,

//= require react

console.log(React); 
console.log(ReactDOM);
var ReactDom = window.ReactDOM

//= require react-select
//= require react_ujs

@reedlaw
Copy link

reedlaw commented Jan 6, 2017 via email

@gauravtiwari
Copy link

@reedlaw Ohh yeah, right sorry? Then, just load it via an external file.

//= require react
//= require global-react-dom
//= require react-select
//= require react_ujs
//  global-react-dom.js
console.log(React);
console.log(ReactDOM);
var ReactDom = window.ReactDOM

@reedlaw
Copy link

reedlaw commented Jan 6, 2017

@gauravtiwari that works but somehow I still get an Error: Cannot find module 'react-dom'

@gauravtiwari
Copy link

@reedlaw Because it's trying to find react-dom inside node-modules directory. But that's weird because you are using asset pipeline right? What setup you using? how are you adding react-select package via gem or npm?

@reedlaw
Copy link

reedlaw commented Jan 6, 2017

@gauravtiwari I followed @maximedelpit above. react-select is a gem from rails-assets.org. My application.js mirrors your example. The two console.logs display fine when I load the page but it bombs on Select.

@gauravtiwari
Copy link

@reedlaw I suggest the easiest option is to download the Dist build and put it in vendor/assets/ and then require it into application.js and application.css manifest.

Please note, you don't need to then explicitly declare that ReactDom variable because it will work with react-rails assigned globals. You can see it here, https://github.com/JedWatson/react-select/blob/master/dist/react-select.js#L683 it's using same window variables.

@reedlaw
Copy link

reedlaw commented Jan 6, 2017

@gauravtiwari the Dist build seems to work. However I get a TypeError: _classnames2["default"] is not a function. That seems to be due to missing dependencies.

@gauravtiwari
Copy link

@reedlaw Use this for classnames, https://rails-assets.org/#/components/classnames (as gem) and dist build for autosize input, https://github.com/JedWatson/react-input-autosize

@gauravtiwari
Copy link

gauravtiwari commented Jan 6, 2017

@reedlaw that's why using asset pipeline nowadays is painful for JS. Take a look at this, https://github.com/gauravtiwari/rails-webpacker (Webpack and Yarn support is coming in Rails 5.1)

@reedlaw
Copy link

reedlaw commented Jan 6, 2017

@guaravTiwari finally it works. Thanks. I'll have to check out rails-webpacker.

@gualopezb
Copy link

@reedlaw what specific versions of react-input-autosize and classnames did you use? I am getting Error: Cannot find module 'react' by requiring the dist build (v1.1.3) of react-input-autosize

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