Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I attach an existing <IMG> element (HTMLImageElement) to a Facebook React.js component?

I have an IMG DOM element I generated with a data-uri. How can I attach it to the React.js "virtual DOM"?

When I try the following:

myImgComponent = React.createClass({

  getInitialState: function() {
    slowGenerateImage((function(_this) {
      return function(img) { /* img is an HTMLImageElement */
        return _this.setState({
          image: img
        });
      };
    })(this));

    return {image: null};
  },

  render: function() {
    return div(
      {}, 
      this.state.image /* image is a raw HTMLImageElement */
    );
  }
});

I get the following error:

Invariant Violation: traverseAllChildren(...): Encountered an invalid child; DOM elements are not valid children of React components. 
like image 263
Shane Brinkman-Davis Avatar asked Jan 11 '23 04:01

Shane Brinkman-Davis


2 Answers

Could you instead just render <img src={this.state.img.src}/>? Or even have slowGenerateImage just generate the src, not create an element, then you can pass that through directly.

like image 125
Paul O'Shannessy Avatar answered Jan 19 '23 11:01

Paul O'Shannessy


This is seems like a bad thing to do, but...

Usage:

return <DomNode node={someDomNode} />;

Note: the below is outdated, as pointed out by @sookie. In newer versions, you use ReactDOM.findDOMNode, and class syntax.


JSBin: http://jsbin.com/hepeboke/2/edit?js,output

Code:

var DomNode = React.createClass({
  componentDidMount: function(){
    this.updateNode(this.props.node);
  },
  componentWillRecieveProps: function(nextProps){
    if (nextProps.node !== this.props.node) {
      this.updateNode(nextProps.node);
    }
  },
  componentWillUnmount: function(){
    this.updateNode(null);
  },
  updateNode: function(node){
    var myNode = this.getDOMNode();
    for (var i=0; i<myNode.children.length; i++) {
      myNode.removeChild(myNode.children[i]);
    }

    if (node) {
      myNode.appendChild(node);
    }
  },
  render: function(){
    return <div />
  }
});

Note: this does insert an extra div, I don't know if there's a way around that but I don't think there is.

like image 20
Brigand Avatar answered Jan 19 '23 11:01

Brigand