反应:模式打开时防止滚动

时间:2019-03-04 18:38:58

标签: javascript reactjs

我有一个自定义模态组件。打开后,背景中不会滚动。

我在下面尝试了此代码:

componentDidMount() {
    document.body.style.overflow = 'hidden';
}

componentWillUnmount() {
    document.body.style.overflow = 'unset';
}

起初似乎起作用,但是当我使用模态组件时,在另一页中,即使关闭了模态也没有滚动。

对此有更好的解决方案吗?

我的模态组件:

export class Modal extends React.Component {

constructor(props) {
    super(props);
}

componentDidMount() {
    document.body.style.overflow = 'hidden';
}

componentWillUnmount() {
    document.body.style.overflow = 'unset';
}

render() {
    return (
        <React.Fragment>
            {this.props.showAt ?
                this.props.show ?
                    <div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
                        {this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                        {this.props.children}
                    </div>
                    : null
                :
                this.props.show ?
                    <div className={`${this.props.className} ${styles.modal}`}>
                        <div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
                            {this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                            {this.props.children}
                        </div>
                    </div> :
                    null}
        </React.Fragment>
    )
  }
}

5 个答案:

答案 0 :(得分:5)

这是一个可用于功能组件的自定义钩子。

import { useEffect } from 'react';

export const useDisableBodyScroll = (open) => {
  useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = 'unset';
    }
  }, [open]);
};
export const Modal = (props) => {
    useDisableBodyScroll(props.show);

    return (
        <React.Fragment>
            {props.showAt ?
                props.show ?
                    <div style={style} className={`${props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!props.showAt ? styles.modalWhiteFixed : ""}`}>
                        {props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                        {props.children}
                    </div>
                    : null
                :
                props.show ?
                    <div className={`${props.className} ${styles.modal}`}>
                        <div style={style} className={`${props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!props.showAt ? styles.modalWhiteFixed : ""}`}>
                            {props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                            {props.children}
                        </div>
                    </div> :
                    null}
        </React.Fragment>
    )
  }
}

答案 1 :(得分:4)

在功能组件中 用于何时安装或卸载

  useEffect(() => {
     document.body.style.overflow = 'hidden';
     return ()=> document.body.style.overflow = 'unset';
  }, []);

或更改show等时

  useEffect(() => {
     show && document.body.style.overflow = 'hidden';
     !show && document.body.style.overflow = 'unset';
  }, [show ]);

答案 2 :(得分:2)

使用状态来跟踪Modal是否打开,如果为true,则仅隐藏滚动。由于您在document.body.style.overflow = 'hidden'中使用componentDidMount,因此该组件仍会挂载,该组件将调用将生命周期隐藏在主体上的生命周期方法。

export class Modal extends React.Component {

constructor(props) {
    super(props);
    this.state = {
      open:false
    }
}

componentDidMount() {    
  if(this.state.open){
    document.body.style.overflow = 'hidden';
  }    
}

componentWillUnmount() {
    document.body.style.overflow = 'unset';
}

render() {
    return (
        <React.Fragment>
            {this.props.showAt ?
                this.props.show ?
                    <div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
                        {this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                        {this.props.children}
                    </div>
                    : null
                :
                this.props.show ?
                    <div className={`${this.props.className} ${styles.modal}`}>
                        <div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
                            {this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
                            {this.props.children}
                        </div>
                    </div> :
                    null}
        </React.Fragment>
    )
  }
}

答案 3 :(得分:0)

在功能组件中,如果浏览器由于隐藏/显示滚动而移动。

  useEffect(() => {
    if (show) {
      document.body.style.overflow = 'hidden';
      document.body.style.paddingRight = '15px';
    }
    return () => {
      document.body.style.overflow = 'unset';
      document.body.style.paddingRight = '0px';
    };
  }, [show]);

答案 4 :(得分:0)

我按照 Mehran Motiee 的方法进行了尝试,但是每次我关闭 cookie 同意时,它都会清除体型。所以我尝试添加班级列表,它起作用了。

  React.useEffect(() => {
    if (show) document.body.classList.add('overflow-hidden');
    else document.body.classList.remove('overflow-hidden');
  }, [show]);