1

This is a generalized question about concepts in react component life cycles. Below is some example code. Please treat the code as just a vague reference.

const Modal = ({
  className,
  variant,
  width,
  withCloseIcon,
  isOpen: propsIsOpen,
  onClose: tellParentToClose,
  renderLink,
  renderContent,
}) => {
  
  const [stateIsOpen, setStateOpen] = useState(false);
  const isControlled = typeof propsIsOpen === 'boolean';
  const isOpen = isControlled ? propsIsOpen : stateIsOpen;
  
  const $modalRef = useRef();
  const $clickableOverlayRef = useRef();

  const closeModal = useCallback(() => {
    if (!isControlled) {
      setStateOpen(false);
    } else {
      tellParentToClose();
    }
  }, [isControlled, tellParentToClose]);


  useEffect(() => {

    console.log('check useEffect')

    document.body.style.overflow = 'hidden'; // why bother? since always return "visible"

    return () => {
      document.body.style.overflow = 'visible';
    };
  }, [isOpen]);

  return (
    <Fragment>

      {isOpen &&
        ReactDOM.createPortal(
          <ScrollOverlay>
            <ClickableOverlay variant={variant} ref={$clickableOverlayRef}>
              <StyledModal
                className={className}
                ref={$modalRef}
              >
                {withCloseIcon && <CloseIcon type="close" variant={variant} onClick={closeModal} />}
                {renderContent({ close: closeModal })}
              </StyledModal>
            </ClickableOverlay>
          </ScrollOverlay>,
          $root,
        )}
    </Fragment>
  );
};

I noticed that in functional components, the function I pass into the hook useEffect() is executed after the return() is executed. (console.log('check useEffect') defined in useEffect() is only executed after some other console log is executed within the renderContent method inside the return() ).

  1. I know by definition, useEffect() is invoked after the component finishes rendering. So what does it mean to have render finished?

  2. what is the relationship between a component "renders" and a component "returns" (React functional component)

  3. within the useEffect(), we are always returning document.body.style.overflow = 'visible';, so why even bother running document.body.style.overflow = 'hidden'; before the return?

Kid_Learning_C
  • 2,605
  • 4
  • 39
  • 71

1 Answers1

2

First of all, let's define some keywords.

What's paint ?

Paint: the user agent has performed a "paint" (or "render") when it has converted the render tree to pixels on the screen. Formally, we consider the user agent to have "rendered" a document when it has performed the update the rendering steps of the event loop.

Paint reference

What's render and how it works?

Basically, the render process is browser painting with little more steps. React needs to define what to (re)render and what not. This process is also called Reconciliation.

More on reconciliation

Question 1

useEffect waits for the browser to finish painting so that your rendering process is not blocked by your useEffect execution. If you don't want to wait for paint to finish you can use useEffectLayout

Question 2

Check this wonderful article from Dan Abramov (One of the core members of React)

Class vs Functional Components

Question 3 and first part of Q1

I can't explain better than this person did. So check this one out as well. https://stackoverflow.com/a/65225493/7942117

Serdar Sayın
  • 389
  • 4
  • 11