Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a React component manipulate an existing DOM node?

Tags:

reactjs

I'd like to add a bit of functionality to some existing server-rendered HTML. Let's say I have a form:

<form>
  <input type="checkbox" /> Show details

  <div class='details'>
    <input type="text" name="first_name" />
    <input type="text" name="last_name" />
  </div>
</form>

The HTML is already generated on the server. I'm wondering, can I use a React component to, say, add/remove a hide class to the .details div whenever the checkbox is checked and unchecked?

I don't want React to re-render the form, since the rest of the page is already handled by the server.

like image 949
Sam Selikoff Avatar asked Nov 26 '14 23:11

Sam Selikoff


People also ask

Can you manipulate the DOM in React?

It can be anything, but if you pass that ref object to a component as a prop called ref , then React will set the current property to the DOM element it creates so you can reference it and manipulate it in your useEffect hook.

Does React interact with DOM?

React will assign the current property with the DOM element when the component mounts, and assign it back to null when it unmounts.

Which method is used for DOM manipulation in React?

findDOMNode() Function This function is generally used to get the DOM node where a particular React component was rendered. This method is very less used like the following can be done by adding a ref attribute to each component itself.


1 Answers

There is a solution but I don't know if it is efficient : You can use the dangerouslySetInnerHTML to create a wrapper over your existing DOM elements.

Consider for example you want to add a swapper on two already existing div elements (https://jsfiddle.net/gdoumenc/a86g58qz/):

// a wrapper just rendering the previous DOM children
var Wrapper = React.createClass({
    render: function() {
        return <div dangerouslySetInnerHTML={{__html: this.props.html}}/>;
    }
});

// a simple swapper
var Swapper = React.createClass({
    getInitialState: function() {
        return {swap: false};
    },
    onClick: function() {
        this.setState({swap: !this.state.swap});
    },
    replace: function(id) {
        if (!(id in this)) {
            var node = document.getElementById(id);
            var elt = document.createElement(node.tagName);
            elt.appendChild(node.childNodes[0]);
            this[id] = elt.innerHTML;
        }
        return this[id];
    },
    render: function() {

        // replace here the elements par wrapped ones
        box1 = <Wrapper html={this.replace('box1')}/>;
        box2 = <Wrapper html={this.replace('box2')}/>;

        if (this.state.swap) {
            content = [box1, box2];
        } else {
            content = [box2, box1];
        };
        return <div>
            {content}<button onClick={this.onClick}>Swap</button>
        </div>;
    }
});

`

like image 181
gdoumenc Avatar answered Oct 02 '22 14:10

gdoumenc