Reputation: 1439
I have a page with a form rendered in the server, it handles validation, and the correct value for the selects.
I want to hide the DOM of that form, and append it into a react component so I can use it in react-router.
const NewItem = React.createClass({
render() {
return (
<div>
<h1>New item</h1>
{/* I WANT THE FORM FROM THE PAGE HERE*/}
</div>
)
}
})
What is the best way to do it?
Upvotes: 6
Views: 17361
Reputation: 2693
Try using portals like in this component:
import {Component} from 'react';
import {createPortal} from 'react-dom';
import PropTypes from 'prop-types';
class DOMPortal extends Component {
constructor(props) {
super(props);
this.el = document.createElement(props.component);
}
componentDidMount() {
this.props.parentEl.appendChild(this.el);
}
componentWillUnmount() {
this.props.parentEl.removeChild(this.el);
}
render() {
return createPortal(
this.props.children,
this.el,
);
}
}
DOMPortal.propTypes = {
parentEl: PropTypes.object.isRequired,
component: PropTypes.string,
};
DOMPortal.defaultProps = {
component: 'div',
};
Now you can pass your external DOM reference as the parentEl props to it:
<DOMPortal parentEl={decorator.contentWidget.domNode}>...children</DOMPortal>
Using this.refs
is "deprecated", try this instead :
render() {
return <div ref={(DOMNodeRef) => {
this.componentRef=DOMNodeRef;
}}>
...
</div>;
}
Then this.componentRef
will be accesible in componentDidMount()
so you can append your external DOM element:
componentDidMount(){
this.componentRef.appendChild(externalDOMelement);
}
Remember that this.componentRef
changes over time (renders()), so you must update it wherever you are passing it to.
Check for a defined reference before using it: if(this.componentRef){// ... your code}
Functional Components' refs are handled differently.
Upvotes: 2
Reputation: 261
React gives us the functionality dangerouslySetInnerHTML. it gives us the support of adding HTML element. for example
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
You can also use portals introduced in react-16 for appending React component anywhere in the tree by using following code.
ReactDOM.createPortal(child, container)
follow following link Portals for refference
Upvotes: 1
Reputation: 54593
You have full access to the DOM in componentDidMount
. You can use refs to access the specific DOM element you want.
var NewItem = React.createClass({
componentDidMount: function () {
this.refs.formTarget.appendChild(myFormDomElement);
},
render: function () {
return React.DOM.div(null,
React.DOM.h1(null, "New item"),
React.DOM.div({ref: "formTarget"}));
}
});
Note that in 0.14, a ref is a raw DOM element. Prior to that a ref was a react component and you had to call React.findDOMNode(it)
to get the actual DOM element.
Upvotes: 2