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

RCo*_*hen 8 javascript reactjs

我有一个自定义模态组件。当它打开时,背景中没有任何滚动。

我在下面尝试了这段代码:

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

componentWillUnmount() {
    document.body.style.overflow = 'unset';
}
Run Code Online (Sandbox Code Playgroud)

乍看起来似乎可行,但是当我使用模式组件时,在另一页中,即使关闭了模式也没有滚动。

有更好的解决方案吗?

我的模态组件:

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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

Meh*_*iee 28

在安装或卸载时的功能组件中

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

或者什么时候show改变等等

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

  • 这是使用挂钩的一个很好的解决方案,但是您的第二个示例有语法错误。`未捕获的语法错误:赋值中的左侧无效`。使用“show &amp;&amp; (obj.key = val)”代替“show &amp;&amp; obj.key = val” (4认同)
  • 直接向 dom 元素添加样式是一个好习惯吗?它会存在任何性能问题或不需要的重新渲染吗? (3认同)
  • 稍微更简洁的语法也修复了语法错误: `useEffect(() =&gt; (document.body.style.overflow = isOpen ? "hidden" : "unset"), [isOpen]);` (2认同)

Ner*_*all 10

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

  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]);
Run Code Online (Sandbox Code Playgroud)


Joh*_*ips 10

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

import { useEffect } from 'react';

export const useDisableBodyScroll = (open) => {
  useEffect(() => {
    if (open) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = 'unset';
    }
  }, [open]);
};
Run Code Online (Sandbox Code Playgroud)
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>
    )
  }
}

Run Code Online (Sandbox Code Playgroud)


Hem*_*har 9

使用state来跟踪Modal是否打开,如果为true,则仅隐藏滚动。由于您使用document.body.style.overflow = 'hidden'in 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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)


Mal*_*nav 7

我有两个函数来处理这个问题,打开模态时和关闭模态时

openModal(){
        this.setState({
            isModalOpen: true
        })
        document.body.style.overflow = 'hidden';
    }

closeModal(){
        this.setState({
            isModalOpen: false
        })
        document.body.style.overflow = 'unset';
    }
Run Code Online (Sandbox Code Playgroud)


Aga*_*Aga 6

短小而优雅

与之前提出的解决方案相同,但最优雅:

  useEffect(() => {
    document.body.style.overflow = isOpen ? "hidden" : "unset";
  }, [isOpen]);
Run Code Online (Sandbox Code Playgroud)


小智 5

对我来说,当我查看节目的节目时,它就起作用了。功能组件中的示例

  useEffect(() => {
    if (show) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = 'visible';
  }, [show]);
Run Code Online (Sandbox Code Playgroud)