Is there a cannonical way of going about doing something like the following without breaking encapsulation?
import React, { Component, PropTypes } from 'react';
class Dashboard extends Component {
constructor(props, context) {
super(props, context);
this.setRef = ::this.setRef;
}
componentDidMount() {
const node = ReactDOM.findDOMNode(this.someRef);
const newHeight = window.innerHeight - node.offsetTop - 30;
node.style.maxHeight = `${newHeight}px`;
}
render() {
return (
<div id="some-element-id" ref={this.setRef}>
</div>
);
}
setRef(ref) {
this.someRef= ref;
}
}
ReactDOM.findDOMNode
seems to be the suggested way of going about this, but this still breaks encapsulation and the documentation has a big red flag to this extent.
In React we can access the DOM element using Refs. Refs provide a way to access DOM nodes or React elements created in the render method. Creating Refs: Refs are created using React. createRef() and attached to React elements via the ref attribute.
createRef can be used in both class and functional components.
React will assign the current property with the DOM element when the component mounts, and assign it back to null when it unmounts.
Deprecations. react-dom : ReactDOM.render has been deprecated. Using it will warn and run your app in React 17 mode.
You should use the component "state" to set the style property of the react element, so you only access the "real" DOM node to calculate the height and then you update the state, re-rendering the component. The react component now has the same information as the real DOM node, so it shouldn't be breaking encapsulation.
Using vanilla JS to provide an example:
var Component = React.createClass({
getInitialState: function(){
return {
style: {},
}
},
componentDidMount: function(){
var node = ReactDOM.findDOMNode(this);
var newHeight = window.innerHeight - node.offsetTop - 30;
this.setState({style: {backgroundColor: '#bbb', height: newHeight.toString() + 'px' }});
},
render: function(){
return React.createElement('div', {style: this.state.style}, 'Height: ' + this.state.style.height);
},
});
You can see it running in this fiddle.
While this technically "breaks encapsulation" in the general sense, if there is no other way to do it (and in this case there is not), then using findDOMNode is your only choice and it is the correct one.
If you find yourself using it repeatedly, you should create a wrapper component to encapsulate that behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With