如何在不渲染子组件的情况下根据子组件的大小更改React父组件的大小?

时间:2018-11-26 14:59:58

标签: javascript reactjs

我创建了一个React组件,该组件可以接收任何组件并将其呈现为弹出窗口。父组件接收要呈现(弹出)的组件。这里渲染的组件是子组件,它使用react-sizeme来获取其大小并传递回父组件。 父组件必须具有子组件的尺寸,因此请调整其高度和宽度。这是代码:

class Popup extends React.Component<IPopupProps,IComponent>{
    constructor(props:IPopupProps){
        super(props);
        this.state={
            childComponent:this.props.children,
            style:{
                height:0,
                width:0
            }
        }     
    }
    
    // This function runs two times, before and after rendering child component
    // & so have an improper visualization as the size is changed twice here
    
    public OnSize = (size:any) =>{
        const width = size.width +20;
        const height =size.height+20;
        this.setState({
            style:{height,
                width             }
        })
    }

    public render(){
        return(
            <div className='popup'>
                <div style={this.state.style} className='popup-content'>
                    <a className="close" onClick={this.props.onExit}>
                            &times;
                    </a>
                    <this.state.childComponent onSize={this.OnSize}/>                    
                </div>
            </div>
        )
    }
}

初始宽度和高度设置为0。因此无法正确渲染。那么有什么方法可以隐藏子组件或避免在父组件获得大小之前渲染它?

编辑:渲染子组件之前,我们无法获得大小。所以有什么技巧可以做到这一点。只需正确弹出一个组件即可。

编辑2:这是PropsBuilder.tsx,它调用Popup.tsx并将组件发送为子代显示

class PopupBuilder extends React.Component<IPopupBuilderProps, IPopup>{
    constructor(props:IPopupBuilderProps){
        super(props);
        this.state = {
            showPopup:false
        }
    }

    public togglePopup = () =>{
        this.setState({
            showPopup:!this.state.showPopup
        })
    }

    public render (){
        return(
            <React.Fragment>

                    <button onClick={this.togglePopup}>{this.props.trigger}</button>

                    <React.Fragment>
                        {this.state.showPopup?<Popup onExit={this.togglePopup} >{this.props.component}</Popup>:null}
                    </React.Fragment>

            </React.Fragment>
            
        )
    }
}

export default PopupBuilder;

1 个答案:

答案 0 :(得分:2)

实际上,这看起来是更一般的DOM / JavaScript问题。

考虑这种情况:

const span = document.createElement('span');
span.innerText = 'hello';
span.getBoundingClientRect() // -> { width: 0, height: 0, top: 0, … }

这是一个指示符,直到元素在DOM中才知道元素的尺寸(在react中渲染);

document.body.appendChild(span);
span.getBoundingClientRect(); // -> {width: 50, height: 16,  …}

在这种情况下,我给您的建议是:

  1. 子级组件应接受父级组件的属性(功能)
  2. 使用React“ ref”功能查找子元素的实际尺寸
  3. 在'componentDidMount'中调用函数(如果子组件可以动态更改,请使用componentDidUpdate),并向其传递子组件尺寸。

如果您无权访问子组件。您可以这样包装它:

// Popup.tsx

class Popup .... {
 ...
   render() {
     <Measurer>{this.props.children}</Measurer>
   }
}

并实现其中提取尺寸的逻辑。 Measurer是Popup的直接子代,您可以控制它们的通信。