Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append to dom in React?

Here's a js fiddle showing the question in action.

In the render function of a component, I render a div with a class .blah. In the componentDidMount function of the same component, I was expecting to be able to select the class .blah and append to it like this (since the component had mounted)

$('.blah').append("<h2>Appended to Blah</h2>");

However, the appended content does not show up. I also tried (shown also in the fiddle) to append in the same way but from a parent component into a subcomponent, with the same result, and also from the subcomponent into the space of the parent component with the same result. My logic for attempting the latter was that one could be more sure that the dom element had been rendered.

At the same time, I was able (in the componentDidMount function) to getDOMNode and append to that

 var domnode = this.getDOMNode(); 
 $(domnode).append("<h2>Yeah!</h2>")

yet reasons to do with CSS styling I wished to be able to append to a div with a class that I know. Also, since according to the docs getDOMNode is deprecated, and it's not possible to use the replacement to getDOMNode to do the same thing

 var reactfindDomNode = React.findDOMNode();
 $(reactfindDomNode).append("<h2>doesn't work :(</h2>");

I don't think getDOMNode or findDOMNode is the correct way to do what I'm trying to do.

Question: Is it possible to append to a specific id or class in React? What approach should I use to accomplish what I'm trying to do (getDOMNode even though it's deprecated?)

var Hello = React.createClass({
    componentDidMount: function(){

       $('.blah').append("<h2>Appended to Blah</h2>");
       $('.pokey').append("<h2>Can I append into sub component?</h2>");
       var domnode = this.getDOMNode();
       $(domnode).append("<h2>appended to domnode but it's actually deprecated so what do I use instead?</h2>")

       var reactfindDomNode = React.findDOMNode();
       $(reactfindDomNode).append("<h2>can't append to reactfindDomNode</h2>");

    },
    render: function() {
        return (
            <div class='blah'>Hi, why is the h2 not being appended here?
            <SubComponent/>
            </div>
        )
    }
});

var SubComponent = React.createClass({

      componentDidMount: function(){
         $('.blah').append("<h2>append to div in parent?</h2>");
      },

      render: function(){
         return(
              <div class='pokey'> Hi from Pokey, the h2 from Parent component is not appended here either?            
              </div>
         )
      }
})

React.render(<Hello name="World" />, document.getElementById('container'));
like image 402
BrainLikeADullPencil Avatar asked Jun 09 '15 01:06

BrainLikeADullPencil


People also ask

How do you add a DOM element in React?

push() - append content in array. unshift() - prepend content in array. Append element in react by using below function : Appending content in array by using push function and with the help of state we are render the content in browser.

What is append in react JS?

append() The Element. append() method inserts a set of Node objects or string objects after the last child of the Element .

How do you update DOM in React?

React keeps two copies of the virtual DOM i.e. the old virtual DOM and the re-rendered virtual DOM which gets created when the render() method is called. The output of the render() method is a javascript object which is mapped to a DOM element. When a component is changed, we get a new react element.

Can you use the DOM in React?

React implements a browser-independent DOM system for performance and cross-browser compatibility. We took the opportunity to clean up a few rough edges in browser DOM implementations. In React, all DOM properties and attributes (including event handlers) should be camelCased.


2 Answers

In JSX, you have to use className, not class. The console should show a warning about this.

Fixed example: https://jsfiddle.net/69z2wepo/9974/

You are using React.findDOMNode incorrectly. You have to pass a React component to it, e.g.

var node = React.findDOMNode(this);

would return the DOM node of the component itself.

However, as already mentioned, you really should avoid mutating the DOM outside React. The whole point is to describe the UI once based on the state and the props of the component. Then change the state or props to rerender the component.

like image 87
Felix Kling Avatar answered Nov 04 '22 14:11

Felix Kling


Avoid using jQuery inside react, as it becomes a bit of an antipattern. I do use it a bit myself, but only for lookups/reads that are too complicated or near impossible with just react components.

Anyways, to solve your problem, can just leverage a state object:

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <script src="https://fb.me/react-0.13.3.js"></script>

  </head>
  <body>
    <div id='container'></div>
    <script>
    'use strict';

var Hello = React.createClass({
    displayName: 'Hello',

    componentDidMount: function componentDidMount() {
        this.setState({
            blah: ['Append to blah'],
            pokey: ['pokey from parent']
        });
    },

    getInitialState: function () {
      return {
        blah: [],
        pokey: []
      };
    },

    appendBlah: function appendBlah(blah) {
        var blahs = this.state.blah;
        blahs.push(blah);
        this.setState({ blah: blahs });
    },
    render: function render() {
        var blahs = this.state.blah.map(function (b) {
            return '<h2>' + b + '</h2>';
        }).join('');
        return React.createElement(
            'div',
            { 'class': 'blah' },
            { blahs: blahs },
            React.createElement(SubComponent, { pokeys: this.state.pokey, parent: this })
        );
    }
});

var SubComponent = React.createClass({
    displayName: 'SubComponent',

    componentDidMount: function componentDidMount() {
        this.props.parent.appendBlah('append to div in parent?');
    },

    render: function render() {
        var pokeys = this.props.pokeys.map(function (p) {
            return '<h2>' + p + '</h2>';
        }).join('');
        return React.createElement(
            'div',
            { 'class': 'pokey' },
            { pokeys: pokeys }
        );
    }
});

React.render(React.createElement(Hello, { name: 'World' }), document.getElementById('container'));
    </script>
  </body>
</html>

Sorry for JSX conversion, but was just easier for me to test without setting up grunt :).

Anyways, what i'm doing is leveraging the state property. When you call setState, render() is invoked again. I then leverage props to pass data down to the sub component.

like image 35
agmcleod Avatar answered Nov 04 '22 15:11

agmcleod