0

I'm trying to use the react.rb gem with opal however I'm having trouble with it.

The following is a simple hello world component, nothing complex.

class Hello_World
    include React::Component

    define_state(:message) { "Hello World!" }

    def initialize(native)
        @native = native
    end

    def component_will_mount
        puts self.message
    end


    def render
        div do
            span do
                self.message
            end
        end
    end

end

Doing this:

puts React.render_to_static_markup(React.create_element(Hello_World))

gets me what I expected, this:

Hello World!
<div><span>Hello World!</span></div>

The problem is when I try to render the template to the dom.

This:

 React.render React.create_element(Hello_World), `document.body`

just gives me:

Uncaught Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.

So I thought it was becuase document.body doesn't exist yet, however none of the following to access the window work (or document):

window #is undefined

$window # is nil

Window # is undefined

There doesn't seem to be an opal command doc for JS equivalents and none of the examples I can find work.

I'm on the verge of pulling my hair out, what do I do?

EDIT:

Doing the following actualy works:

I'm not using jquery so I have to do the following to get document.ready:

document.ready = function (event) {
    document.addEventListener("DOMContentLoaded", event)
}

%x|document.ready(function(){
    #{
        React.render React.create_element(Hello_World), `document.getElementById('mount_point')`
    }
})|

but it's suuuuper hacky.

ylluminate
  • 12,102
  • 17
  • 78
  • 152
Thermatix
  • 2,757
  • 21
  • 51
  • Are those really backticks or is that a copy paste error: `\`document.body\``. Because those backticks should be single quotes: `'document.body'`. EDIT: Hmz, the opal/react examples are full of backticks, so I might be wrong here. – zwippie Aug 17 '15 at 11:39
  • They are backticks, and I've tried with normal quotes as well, it errors `Target container is not a DOM element.` – Thermatix Aug 17 '15 at 11:41
  • Does this work? `React.render React.create_element(Hello_World), \`document.getElementById('hello_word')\``. You should also create a `div #hello_world` in your template. – zwippie Aug 17 '15 at 11:44
  • Another question: is that call to `React.render` wrapped in a `Document.ready?` block? – zwippie Aug 17 '15 at 11:49
  • I do not because I can't access the document object from opal, it just won't let me in the exact same way I can't access the window object (I forgot to add that in, so I have, my bad). I'm not using jquery so I can't do `document.ready` without bootstrapping my own, (which works btw, just a wrapper for `document.addEventListener("DOMContentLoaded", event)`. Just came up with a hacky solution. – Thermatix Aug 17 '15 at 12:03

1 Answers1

0

The problem is that body.getElementById('mount_point') was returning nil, this was because the script was executing before the dom was ready.

Since I'm not using Jquery and for some reason I couldn't access the document object I was having trouble. In the end though I was able to create a method to deal with that for me.

So, defining this:

def ready
    %x|document.addEventListener("DOMContentLoaded", function(){
        #{yield}
    })|
end

allows me to do:

ready do
    React.render React.create_element(Hello_World), `document.getElementById('mount_point')`
end
Thermatix
  • 2,757
  • 21
  • 51