首页 > 解决方案 > React - execute javascript after bootstrap modal is completely rendered and visible

问题描述

I'm working on a React front-end that uses Reactstrap, in which I'm creating my own reusable modal component. Whenever there is too much content for the modal, it becomes scrollable and to make that clear to the user, I created an indicator at the bottom of the modal. (example screenshot)

The indicator sticks at the bottom of the modal while scrolling and I make it disappear when the user reaches the end (check onscroll event and moreContent state in code below).

So far so good, but my problem is that I can't find a way to check if I initially have to show the indicator when rendering the modal. Right now the moreContent state is initially set to true, but that should depend on whether the modal is scrollable or not.

I tried:

The code for my modal component:

    import React, {useEffect, useState} from 'react';
    import {Button, Modal, ModalBody, ModalHeader} from "reactstrap";
    
    const MyModal = (props) => {
        const [moreContent, setMoreContent] = useState(true);
        const ref = React.useRef();
    
        useEffect(() => {
            console.log("scrollHeight", ref.current._element.scrollHeight);
            console.log("scrollTop", ref.current._element.scrollTop);
            console.log("clientHeight", ref.current._element.clientHeight);
        });
    
        const onScroll = (event) => {
            if (moreContent) {
                setMoreContent(event.target.scrollHeight - event.target.scrollTop !== event.target.clientHeight);
            }
        }
    
        return (
            <Modal isOpen={props.isOpen} toggle={props.closeHandler} centered={true} scrollable={true} className="my-modal" onScroll={onScroll} ref={ref}>
                <ModalHeader tag="div" toggle={props.closeHandler}>
                    ...
                </ModalHeader>
                <ModalBody>
                    {props.children}
                    {moreContent &&
                        <div className="modal-scroll-down">
                            <i className="fa fa-arrow-down mr-4"></i> MEER <i className="fa fa-arrow-down ml-4"></i>
                        </div>
                    }
                </ModalBody>
            </Modal>
        )
    };
    
    MyModal.defaultProps = {
        showCloseButton : true
    }
    
    export default MyModal;

Any tip, advice, workaround is welcome.

Thanks in advance!

标签: reactjsreactstrap

解决方案


The issue here is that you are attaching ref to a Modal which is not a DOM element and therefore will not have these properties scrollHeight, scrollTop, and clientHeight. Furthermore even if it was a DOM element, it is not the element with the scrollbar - it is actually ModalBody. But, to make matters worst, it looks like Reactstrap does not really expose a prop for you attach a forwarded ref to the ModalBody.

To solve this you can replace ModalBody with a div - this is where we can attach a ref to.

<Modal
  isOpen={props.isOpen}
  toggle={props.closeHandler}
  centered={true}
  scrollable={true}
  className="my-modal"
  onScroll={onScroll}
  onOpened={onOpened}
>
  <ModalHeader tag="div" toggle={props.closeHandler}>
    modal header
  </ModalHeader>

  <div ref={ref} style={{ overflowY: "auto", padding: "16px" }}>
    {props.children}
    {moreContent && (
      <div className="modal-scroll-down">
        <i className="fa fa-arrow-down mr-4"></i> MEER{" "}
        <i className="fa fa-arrow-down ml-4"></i>
      </div>
    )}
  </div>
</Modal>

Pay attention to the onOpened prop I attached to <Modal>, this answers what you sought:

execute javascript after bootstrap modal is completely rendered and visible

const onOpened = () => {
  setMoreContent(
    ref.current.scrollHeight - ref.current.scrollTop !==
      ref.current.clientHeight
  );
};

Edit Reactstrap Modal


推荐阅读