Using React within an Atom Package


#1

Is it possible to run React within an Atom package?

I keep getting a React error indicating that the Atom views are not DOM elements.

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

In this case I’m simply running a basic React demo within the view.coffee generated file

React = require 'react'

module.exports =
class ReactTestView
  constructor: ->
    @element = document.createElement('div')
    @element.setAttribute 'id', 'react-render'

    Component = React.createClass
      displayName: 'Component'

      render: ->
        React.DOM.div("Hello #{@props.name}!")

    component = React.createFactory(Component)
    React.render(component(name: "World"), document.getElementById 'react-render')

I understand React is no longer used in Atom, but I would like to create a plugin of significant complexity.

If it can’t work, alternatively, does anyone know of an example using a variant of Flux with Space-Pen? Possibly utilizing atoms event emitters.


#2

Does anyone know of a working example using ‘react-for-atom’?

https://www.npmjs.com/package/react-for-atom


#3

Others will be able to give more precise instructions here, but have you thought of checking the shadow DOM for your element instead?


#4

I think that may be part of the issue. Targeting inside of shadow DOM may explain the underlying error message:

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

However, I’m unable to even get a ‘hello world’ working when targeting the document.body.


#5

A working solution: atom-react-starter, and demo example: atom-ftp-editor.


#6

The approach you took in atom-react-starter is the pattern Nuclide has adopted as well. The main.js file is responsible for creating the mounting node for the root React component.

const FooComponent = ...;
const React = ...;

let panel;
let root;

module.exports = {
  activate() {
    root = document.createElement('div');
    React.render(
      <FooComponent />,
      root
    );
    panel = atom.workspace.addBottomPanel({item: root});
  },
  deactivate() {
    React.unmountComponentAtNode(root);
    panel.destroy();
  }
};

#7

I’ve developer a larger working app, the code is available online: site, github