React Rails Component is not defined - ruby-on-rails

I'm trying to get the react-rails gem (version 2.1) working in my Rails 4.2.4 app. I've gone through the setup steps in the Readme and I'm using webpacker for the js preprocessing. I have a component inside of app/javascript/components/label.js that looks like this:
import React, {PureComponent} from 'react';
import ReactDOM from 'react-dom'
export default class Label extends PureComponent {
render () {
return (
<div>Something rendered in React</div>
)
}
}
And then I reference this in my view with the following line:
= react_component("Label")
As far as I can see from the Readme, this should be all that is necessary in order to render the component (provided the application pack is included in the layout, which it is)
= javascript_pack_tag 'application'
So I'm confused as to why I'm getting the error in my browser that the component is not defined.
Uncaught ReferenceError: Label is not defined
Opening app/javascript/packs/application.js I can see the following:
console.log('Hello World from Webpacker')
// Support component names relative to this directory:
var componentRequireContext = require.context("components", true)
var ReactRailsUJS = require("react_ujs")
ReactRailsUJS.useContext(componentRequireContext)
First I verified that the console log is displayed in the browser (it is). I'm not sure what componentRequireContext does, but if it is relative to the current file, then it seems odd that it points to components and not ../components, but changing this doesn't render the component. However, I can get the component rendering if I add the following line:
window.Label = require('../components/label.js');
I thought the React Rails gem took care of this though, provided the components were saved in the app/javascript/components directory? There's nothing in the Readme that says that I need to explicitly declare and require the component, or am I mistaken?

It looks like you have a capitalization issue. You named the file 'label.js' but you are looking for '= react_component("Label")' So it looks and doesn't find what Label is. Then when you set Label on the window then react is like "Oh ok, Label is actually label.js." and it does stuff. TLDR capitalization matters.

Related

Uncaught ReferenceError: exports is not defined react-rails

I need to add react-rails to my rails 4 app, but it's giving me hard time to figure out.
my project uses sprockets for assets:precompilation,
this is my component:
import React from "react"
class Sidebar extends React.Component {
render() {
return (<p> hello from react </p> );
}
}
export default Sidebar;
when I load the page everything works fine, except for the react component, which is just rendered as a div in the html, and in the console I see:
Sidebar.self.js?body=1:1 Uncaught ReferenceError: exports is not defined
at Sidebar.self.js:1:23
there's an initial snippet added there:
Object.defineProperty(exports, "__esModule", {
value: true
});
That causes the problem.
I tried everything I could find:
Webpacker (but that gave way more troubles so I removed it)
installing https://github.com/TannerRogalsky/sprockets-es6
Typescript ReferenceError: exports is not defined
React uncaught reference error: exports is not defined
and more. I'm not sure what I'm doing wrong (or maybe I misused one of the solutions above?)
update
I figured that I can send babel configuration options via react-rails gem using:
Rails.application.config.react.jsx_transform_options = {
plugins: ["#babel/preset-react"],
loose: ["es6.modules"]
}
I'm not sure which plugins I should use, but this doesn't appear to be affecting a thing, except that it's not ignored, if I write something that is not recognised I do get an exception.

How to migrate requiring of select2.js from sprockets to webpacker

I'm in the process of migrating a Rails 5.1.5 project, which uses CoffeeScript, from using sprockets to using webpacker. The project also uses select2.js. With sprockets, I did the following:
Install jquery-rails (jQuery is a dependency for select2).
Put select2.js code in vendor/assets/javscripts.
In application.js.coffee, add:
#= require select2
After that I was able to use select2 to in my application.js.coffee file:
$(document).on 'turbolinks:load' ->
$('select').select2
So far I've described the pretty standard way of including/using javascript libraries with sprockets.
However, with webpacker I can't make select2 work and I'm not sure why. I have two hypothesis:
I'm not importing/requiring it properly;
it doesn't find jQuery at some point of the load process;
So for jQuery, I did the following:
yarn add jquery
included in my environment.js:
const webpack = require('webpack');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}));
I've removed the jquery-rails gem, as well as #= require 'jquery' and tested that jquery works, so I guess I have correctly included it. However, I tried several ways of importing select2 (using es6 imports) and none of them worked. I tried:
import select2 from 'select2';
import select2 from 'select2/dist/js/select2'
import select2 from 'select2/dist/js/select2.js'
import 'select2/dist/js/select2.js'
I even tried to import it from the old vendor location by writing inside app/javascript/pack/application.js.coffee:
import '../../../vendor/assets/javascripts/select2'
I can confirm that the file contents is imported, as I put a console.log within the select2 file under node_modules/select2/dist/js/select.js and it did get printed. However, I also get the error TypeError: $(...).select2 is not a function when I execute $('select').select2() in the browser's dev tool console.
What am I missing or doing wrong?
P.S. I can provide much more info, but I didn't want my question to get any more bloated.
P.P.S. With my modest JS knowledge, I looked at the source code but couldn't recognize what exactly they are exporting and how am I supposed to import it.
I know this is an old post, but just in case someone else could benefit:
app/javascript/packs/application.js
...other requires...
require('select2')
window.Rails = Rails
import 'bootstrap'
...other imports...
import 'select2'
import 'select2/dist/css/select2.css'
$(document).on("turbolinks:load", () => {
$('.select2').select2()
})
My similar problem
I have stumble upon the same problem with another web component (Switchery):
I imported the component with yarn add switchery (no error)
I could import it correctly through WebPack with import 'switchery' (no error bundling the pack)
But when I was trying to use the Switchery object in the browser like they say in the doc:
var elem = document.querySelector('.js-switch');
var init = new Switchery(elem);
I would get the error: ReferenceError: Switchery is not defined
Note: I didn't want to install RequireJS as WebPack is supposed to do the same thing (and even better) nowadays.
My solution:
The problem was the webpack doesn't expose the pack-generated variables and classes in the global scope!
So to fix this, I needed to do two things:
Explicitly give a name to the imported class from Switchery:
import Switchery from 'switchery'
Use this Class only in the same JS file where the import was done
Testing hack:
If you want to try that out and "go back" to the mess that sprocket allowed, in the same file, you can expose "globally" the variable so you can use in from the browser:
import Switchery from 'switchery'
window.Switchery = Swicthery
now you can execute the switchery almost like in the example:
var init = new window.Switchery(elem);
Hope that helps...

How to use rails webpack loaded js in js erb template

I am using webpacker gem in rails 5.0 app, but I can't get the javascript to execute/be available in the js.erb I'm hitting on validation error. I'm sure that I'm violating some simple premise here, but can't find the answer and no compile or console errors are present. I do have the <%= javascript_pack_tag 'application' %> in my application.html.erb
Here is the setup:
app/javascript/packs/application.js:
import * as CustomerSession from 'customer_sessions';
console.log('Hello World from Webpacker');
app/javascript/customer_sessions/index.js:
export { univgwTabs } from './univgwTabs';
app/javascript/customer_sessions/univgwTabs:
export let univgwTabs = () => {
console.log('hi');
};
js erb template called on validation error of form:
$("#right_side_right_bottom_target").html("<%= j render partial: 'generic_object_new' %>");
CustomerSession.univgwTabs();
Global.resizeWindow();
If there is no issue with console.log(CustomerSession) in the location where you are importing it then the simplest fix I found was to just assign the imported variable as one of the global windows properties.
// in packs/application.js (or wherever your pack is)
// import
import * as CustomerSession from 'customer_sessions';
// assign
window.CustomerSession = CustomerSession
Assuming that there is no issues with webpacker, you should now be able to console.log(CustomerSession) in the console or your js.erb file.

jsx doesn't seem to transpile correctly

I am using the react-rails gem in a Rails(4.2.7) project. This is the only modification I've made to my default Gemfile:
gem 'react-rails'
I've defined a component in a .jsx file using es6 syntax:
class Foo extends React.Component {
render () {
return (<h1>hello</h1>)
}
}
This works fine, but when I attempt to import a js module, I get an error:
import ReactTransitionGroup from 'react-addons-transition-group'
class Foo extends React.Component {
render () {
return (<h1>hello</h1>)
}
}
foo.es6.self-69f3a42….js?body=1:11 Uncaught ReferenceError: require is not defined
It seems to me that if I'm not transpiling the jsx correctly then I would be getting an error in the first case, but I'm not. I've been using jsx all day long with no issues until I tried to use import.
I've tried adding the following to my Gemfile:
gem 'sprockets-es6'
gem 'babel-transpiler'
I've tried adding this to config/environments/development.rb:
config.react.jsx_transformer_class = React::JSX::BabelTransformer
And I've tried generating the component using the rails react component generator with the --es6 flag:
rails g react:component Foo --es6
What am I missing?
So here's how I resolved my issue: since I'm using the 'react-rails' gem, the addons are available via a configuration option - I added the following to config/application.rb:
config.react.addons = true
Then in my .jsx file, instead of import, this is the syntax I used to have access to ReactTransitionGroup:
var ReactTransitionGroup = React.addons.ReactTransitionGroup
I still don't understand, but maybe someday I will, why the import statement transpiles to require which is undefined, and how that could be fixed by anything other than defining require, or transpiling to something that is defined.

How to deploy dart polymer with no index.html entry point

I have a dart web application using polymer. I can successfully run it with Dartium using boot.js. However, my index.html file is actually a Django template in another git repo for the project. Its uses template inheritance, among other things, so its not just a normal HTML file.
My goal is to have a Makefile compile the project on request. Currently, pub deploy will compile all the code, and it will run in non-dart browsers. However, my custom polymer elements do not end up being registered. They all show up as blank. Is this kind of setup even possible, that is, to not have an index.html entry point and build custom polymer elements? I could create a dummy buid.html to satisfy the entry-point requirement, but this seems like a sub-optimal solution.
My current buid.dart looks like:
import 'dart:io';
import 'package:polymer/component_build.dart';
import 'package:polymer/deploy.dart' as deploy;
main() {
build(new Options().arguments, [])
.then((_) => deploy.main());
}
and the output:
'package:polymer/component_build.dart': Error: line 68 pos 29: \
ambiguous reference: 'JSON' is defined in library 'dart:convert' \
and also in 'dart:io'
var message = JSON.encode([jsonMessage]);
The only way is to provide some HTML file as entry point. It doesn't matter when you use another HTML file in production if it contains the necessary script tags.

Resources