UNPKG

react-height

Version:

Component-wrapper to determine and report children elements height

108 lines (83 loc) 2.4 kB
import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; const getElementHeightDefault = el => el.clientHeight; export class ReactHeight extends PureComponent { static propTypes = { children: PropTypes.node.isRequired, onHeightReady: PropTypes.func.isRequired, hidden: PropTypes.bool, dirty: PropTypes.bool, getElementHeight: PropTypes.func }; static defaultProps = { hidden: false, dirty: true, getElementHeight: getElementHeightDefault }; constructor(props) { super(props); this.state = { dirty: props.dirty, height: 0 }; } componentDidMount() { const {getElementHeight} = this.props; const height = getElementHeight(this.wrapper); const dirty = false; this.setState({height, dirty}, () => { const {onHeightReady} = this.props; const {height: currentHeight} = this.state; onHeightReady(currentHeight); }); } // eslint-disable-next-line react/no-deprecated componentWillReceiveProps({children, dirty}) { const {children: oldChildren} = this.props; if (children !== oldChildren || dirty) { this.setState({dirty: true}); } } componentDidUpdate() { const {getElementHeight} = this.props; const height = getElementHeight(this.wrapper); const dirty = false; const {height: currentSavedHeight} = this.state; if (height === currentSavedHeight) { // eslint-disable-next-line react/no-did-update-set-state this.setState({dirty}); } else { // eslint-disable-next-line react/no-did-update-set-state this.setState({height, dirty}, () => { const {onHeightReady} = this.props; const {height: currentHeight} = this.state; onHeightReady(currentHeight); }); } } setWrapperRef = el => { this.wrapper = el; }; render() { const { onHeightReady: _onHeightReady, getElementHeight: _getElementHeight, dirty: _dirty, hidden, children, ...props } = this.props; const {dirty} = this.state; if (hidden && !dirty) { return null; } if (hidden) { return ( <div style={{height: 0, overflow: 'hidden'}}> <div ref={this.setWrapperRef} {...props}>{children}</div> </div> ); } return <div ref={this.setWrapperRef} {...props}>{children}</div>; } }