Reputation: 1098
I'm currently learning ReactJS and how to work with Ruby on Rails as its backend, so I apologize if I'm making dumb assumptions, feel free to scold me.
I'm following a tutorial where the author is using Coffeescript instead of ES6 to handle his ReactJS code.
He provides an example component similar to this (coffeescript):
@Rows = React.createClass
render ->
React.DOM.div
className: 'rows'
React.DOM.h1
className: 'title'
'Rows'
This has two errors. The first one pertains to React.createClass
which I found out has been deprecated and no longer works. Instead I'm using createReactClass
. Good. But now, React.DOM.h1
gives an error saying Uncaught TypeError: Cannot read property 'h1' of undefined
, same for whichever other HTML tag I use. I assume it's due to createReactClass
not providing the necessary functionality previously provided by React.createClass
.
Anyway, while researching for another error indirectly related to this, I found someone suggesting to use something like this:
@Rows = React.createClass
render ->
div
className: 'rows'
h1
className: 'title'
'Rows'
So, cutting off the React.DOM
part. This gives another type of error, saying: Uncaught ReferenceError: div is not defined
. Again, I'm assuming it's due to the change to React.createClass
.
Is there a way to use React with CoffeeScript, such that I could use it like this:
@Rows = createReactClass
render ->
div
className: 'rows'
h1
className: 'title'
'Rows'
without having to open and close HTML tags, and without React.DOM
?
I don't know if it's possible at all, or if it ever worked, or even if there're many ways to achieve something with similar results. I'm just curious to know if there's a way to do it like this before I dive deeper onto React.
Thanks!
I've made some progress, though I'm still getting an error. I tried the following:
import React from 'react'
import ReactDom from 'react-dom'
{div, h1, p} = ReactDom
class Rows extends React.Component
render: ->
h1
className: 'col-md-12'
'Rows'
export default Rows
This gives the following error: Uncaught TypeError: h1 is not a function
.
Upvotes: 2
Views: 2483
Reputation: 1098
Here's what finally worked
React = require('react')
PropTypes = require('prop-types')
ReactDom = require('react-dom-factories')
createReactClass = require('create-react-class')
{div, h1} = ReactDom
Rows = createReactClass
render: ->
div
className: 'col-md-12'
h1
className: 'title'
'Rows'
export default Rows
So I've been using React 16 and it's incredible how many things have changed in the last 6 months. I'm TOTALLY new to React, so I had absolutely no idea how this worked, but I managed to use the code above without errors.
First:
ReactDom = require('react-dom-factories')
This is the one I was missing. I was getting errors that div
and h1
weren't functions, or weren't defined. So it turns out that per the documentation React.DOM
is now available as react-dom-factories
:
The deprecations introduced in 15.x have been removed from the core package. React.createClass is now available as create-react-class, React.PropTypes as prop-types, React.DOM as react-dom-factories, react-addons-test-utils as react-dom/test-utils, and shallow renderer as react-test-renderer/shallow.
Second:
If anyone else runs onto this and you get errors that say Cannot find module "react-dom-factories"
, it means you have to add them to your webpacker with this:
yarn add react-dom-factories
You may also have to add create-react-class
and prop-types
, if you're following my example above.
Lastly:
Be sure the extension of your coffeescript file is simply .coffee. If you use .js.coffee
or .jsx.coffee
you'll get errors that the component cannot be found.
I'm not 100% sure if this is necessary, but I also added cjsx-loader
to my webpacker when I was searching for a solution. It's a coffee-react-transform loader module for Webpack.
UPDATE: This last part wasn't necessary. I made a new project and this wasn't required at all.
Upvotes: 3
Reputation: 6548
You can use coffeescript with React without JSX. I think it makes for much cleaner code:
React = require('react')
ReactDOM = require('react-dom')
{div, h1} = ReactDom
class Rows extends React.Component
render: ->
div
className: 'rows'
h1
className: 'title'
'Rows'
module.exports = React.createFactory Rows
ReacDom
to use the DOM elements directly
Rows = require('./rows')
class OtherComponent extends React.Component
.
.
.
render: ->
div
className: 'container'
Rows()
Upvotes: 3