diff --git a/package.json b/package.json
index 5f4f4e377b..3d361a4923 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
     "moment": "^2.29.4",
     "moment-timezone": "^0.5.34",
     "prop-types": "^15.8.1",
-    "react-overlays": "^4.1.1",
+    "react-overlays": "^5.2.0",
     "uncontrollable": "^7.2.1"
   },
   "bugs": {
diff --git a/src/Month.js b/src/Month.js
index 2bf573da91..997f48fd8a 100644
--- a/src/Month.js
+++ b/src/Month.js
@@ -9,8 +9,9 @@ import { notify } from './utils/helpers'
 import getPosition from 'dom-helpers/position'
 import * as animationFrame from 'dom-helpers/animationFrame'
 
-import Popup from './Popup'
-import Overlay from 'react-overlays/Overlay'
+/* import Popup from './Popup'
+import Overlay from 'react-overlays/Overlay' */
+import PopOverlay from './PopOverlay'
 import DateContentRow from './DateContentRow'
 import Header from './Header'
 import DateHeader from './DateHeader'
@@ -204,11 +205,40 @@ class MonthView extends React.Component {
   }
 
   renderOverlay() {
-    let overlay = (this.state && this.state.overlay) || {}
-    let { accessors, localizer, components, getters, selected, popupOffset } =
-      this.props
+    let overlay = this.state?.overlay ?? {}
+    let {
+      accessors,
+      localizer,
+      components,
+      getters,
+      selected,
+      popupOffset,
+      handleDragStart,
+    } = this.props
+
+    const onHide = () => this.setState({ overlay: null })
 
     return (
+      <PopOverlay
+        overlay={overlay}
+        accessors={accessors}
+        localizer={localizer}
+        components={components}
+        getters={getters}
+        selected={selected}
+        popupOffset={popupOffset}
+        ref={this.containerRef}
+        handleKeyPressEvent={this.handleKeyPressEvent}
+        handleSelectEvent={this.handleSelectEvent}
+        handleDoubleClickEvent={this.handleDoubleClickEvent}
+        handleDragStart={handleDragStart}
+        show={!!overlay.position}
+        overlayDisplay={this.overlayDisplay}
+        onHide={onHide}
+      />
+    )
+
+    /* return (
       <Overlay
         rootClose
         placement="bottom"
@@ -237,7 +267,7 @@ class MonthView extends React.Component {
           />
         )}
       </Overlay>
-    )
+    ) */
   }
 
   measureRowLimit() {
diff --git a/src/PopOverlay.js b/src/PopOverlay.js
new file mode 100644
index 0000000000..3499bec621
--- /dev/null
+++ b/src/PopOverlay.js
@@ -0,0 +1,95 @@
+import React, { useRef } from 'react'
+import PropTypes from 'prop-types'
+import { Overlay } from 'react-overlays'
+import Popup from './Popup'
+
+function CalOverlay({
+  containerRef,
+  popupOffset = 5,
+  overlay,
+  accessors,
+  localizer,
+  components,
+  getters,
+  selected,
+  handleSelectEvent,
+  handleDoubleClickEvent,
+  handleKeyPressEvent,
+  handleDragStart,
+  onHide,
+  overlayDisplay,
+}) {
+  const popperRef = useRef(null)
+  if (!overlay.position) return null
+
+  let offset
+  if (!isNaN(popupOffset)) {
+    offset = { x: popupOffset, y: popupOffset }
+  }
+
+  const { position, events, date, end } = overlay
+  return (
+    <Overlay
+      rootClose
+      flip
+      show
+      placement="bottom"
+      onHide={onHide}
+      target={overlay.target}
+    >
+      {({ props }) => (
+        <Popup
+          {...props}
+          containerRef={containerRef}
+          ref={popperRef}
+          target={overlay.target}
+          offset={offset}
+          accessors={accessors}
+          getters={getters}
+          selected={selected}
+          components={components}
+          localizer={localizer}
+          position={position}
+          show={overlayDisplay}
+          events={events}
+          slotStart={date}
+          slotEnd={end}
+          onSelect={handleSelectEvent}
+          onDoubleClick={handleDoubleClickEvent}
+          onKeyPress={handleKeyPressEvent}
+          handleDragStart={handleDragStart}
+        />
+      )}
+    </Overlay>
+  )
+}
+
+const PopOverlay = React.forwardRef((props, ref) => (
+  <CalOverlay {...props} containerRef={ref} />
+))
+
+PopOverlay.propTypes = {
+  popupOffset: PropTypes.oneOfType([
+    PropTypes.number,
+    PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
+  ]),
+  overlay: PropTypes.shape({
+    position: PropTypes.object,
+    events: PropTypes.array,
+    date: PropTypes.instanceOf(Date),
+    end: PropTypes.instanceOf(Date),
+  }),
+  accessors: PropTypes.object.isRequired,
+  localizer: PropTypes.object.isRequired,
+  components: PropTypes.object.isRequired,
+  getters: PropTypes.object.isRequired,
+  selected: PropTypes.object,
+  handleSelectEvent: PropTypes.func,
+  handleDoubleClickEvent: PropTypes.func,
+  handleKeyPressEvent: PropTypes.func,
+  handleDragStart: PropTypes.func,
+  onHide: PropTypes.func,
+  overlayDisplay: PropTypes.func,
+}
+
+export default PopOverlay
diff --git a/src/Popup.js b/src/Popup.js
index a19fb3cf7e..5d14d31f2d 100644
--- a/src/Popup.js
+++ b/src/Popup.js
@@ -1,136 +1,125 @@
+import React, { useLayoutEffect } from 'react'
 import PropTypes from 'prop-types'
-import React from 'react'
 import getOffset from 'dom-helpers/offset'
-import getScrollTop from 'dom-helpers/scrollTop'
-import getScrollLeft from 'dom-helpers/scrollLeft'
 
+import useClickOutside from './hooks/useClickOutside'
 import EventCell from './EventCell'
 import { isSelected } from './utils/selection'
 
-class Popup extends React.Component {
-  componentDidMount() {
-    let { popupOffset = 5, popperRef } = this.props,
-      { top, left, width, height } = getOffset(popperRef.current),
-      viewBottom = window.innerHeight + getScrollTop(window),
-      viewRight = window.innerWidth + getScrollLeft(window),
-      bottom = top + height,
-      right = left + width
-
-    if (bottom > viewBottom || right > viewRight) {
-      let topOffset, leftOffset
-
-      if (bottom > viewBottom)
-        topOffset = bottom - viewBottom + (popupOffset.y || +popupOffset || 0)
-      if (right > viewRight)
-        leftOffset = right - viewRight + (popupOffset.x || +popupOffset || 0)
+/**
+ * Changes to react-overlays cause issue with auto positioning,
+ * so we need to manually calculate the position of the popper,
+ * and constrain it to the Month container.
+ */
+function getPosition({ target, offset, container, box }) {
+  const { top, left, width, height } = getOffset(target)
+  const {
+    top: cTop,
+    left: cLeft,
+    width: cWidth,
+    height: cHeight,
+  } = getOffset(container)
+  const { width: bWidth, height: bHeight } = getOffset(box)
+  const viewBottom = cTop + cHeight
+  const viewRight = cLeft + cWidth
+  const bottom = top + bHeight
+  const right = left + bWidth
+  const { x, y } = offset
+  const topOffset = bottom > viewBottom ? top - bHeight - y : top + y + height
+  const leftOffset = right > viewRight ? left + x - bWidth + width : left + x
 
-      this.setState({ topOffset, leftOffset }) //eslint-disable-line
-    }
+  return {
+    topOffset,
+    leftOffset,
   }
+}
 
-  render() {
-    let {
-      events,
-      selected,
-      getters,
-      accessors,
-      components,
-      onSelect,
-      onDoubleClick,
-      onKeyPress,
-      slotStart,
-      slotEnd,
-      localizer,
-      popperRef,
-    } = this.props
-
-    let { width } = this.props.position,
-      topOffset = (this.state || {}).topOffset || 0,
-      leftOffset = (this.state || {}).leftOffset || 0
-
-    let style = {
-      top: -topOffset,
-      left: -leftOffset,
-      minWidth: width + width / 2,
-    }
+function Pop({
+  containerRef,
+  accessors,
+  getters,
+  selected,
+  components,
+  localizer,
+  position,
+  show,
+  events,
+  slotStart,
+  slotEnd,
+  onSelect,
+  onDoubleClick,
+  onKeyPress,
+  handleDragStart,
+  popperRef,
+  target,
+  offset,
+}) {
+  useClickOutside({ ref: popperRef, callback: show })
+  useLayoutEffect(() => {
+    const { topOffset, leftOffset } = getPosition({
+      target,
+      offset,
+      container: containerRef.current,
+      box: popperRef.current,
+    })
+    popperRef.current.style.top = `${topOffset}px`
+    popperRef.current.style.left = `${leftOffset}px`
+  }, [offset.x, offset.y, target])
 
-    return (
-      <div
-        style={{ ...this.props.style, ...style }}
-        className="rbc-overlay"
-        ref={popperRef}
-      >
-        <div className="rbc-overlay-header">
-          {localizer.format(slotStart, 'dayHeaderFormat')}
-        </div>
-        {events.map((event, idx) => (
-          <EventCell
-            key={idx}
-            type="popup"
-            localizer={localizer}
-            event={event}
-            getters={getters}
-            onSelect={onSelect}
-            accessors={accessors}
-            components={components}
-            onDoubleClick={onDoubleClick}
-            onKeyPress={onKeyPress}
-            continuesPrior={localizer.lt(
-              accessors.end(event),
-              slotStart,
-              'day'
-            )}
-            continuesAfter={localizer.gte(
-              accessors.start(event),
-              slotEnd,
-              'day'
-            )}
-            slotStart={slotStart}
-            slotEnd={slotEnd}
-            selected={isSelected(event, selected)}
-            draggable={true}
-            onDragStart={() => this.props.handleDragStart(event)}
-            onDragEnd={() => this.props.show()}
-          />
-        ))}
-      </div>
-    )
+  const { width } = position
+  const style = {
+    minWidth: width + width / 2,
   }
+  return (
+    <div style={style} className="rbc-overlay" ref={popperRef}>
+      <div className="rbc-overlay-header">
+        {localizer.format(slotStart, 'dayHeaderFormat')}
+      </div>
+      {events.map((event, idx) => (
+        <EventCell
+          key={idx}
+          type="popup"
+          localizer={localizer}
+          event={event}
+          getters={getters}
+          onSelect={onSelect}
+          accessors={accessors}
+          components={components}
+          onDoubleClick={onDoubleClick}
+          onKeyPress={onKeyPress}
+          continuesPrior={localizer.lt(accessors.end(event), slotStart, 'day')}
+          continuesAfter={localizer.gte(accessors.start(event), slotEnd, 'day')}
+          slotStart={slotStart}
+          slotEnd={slotEnd}
+          selected={isSelected(event, selected)}
+          draggable={true}
+          onDragStart={() => handleDragStart(event)}
+          onDragEnd={() => show()}
+        />
+      ))}
+    </div>
+  )
 }
 
+const Popup = React.forwardRef((props, ref) => (
+  <Pop {...props} popperRef={ref} />
+))
 Popup.propTypes = {
-  position: PropTypes.object,
-  popupOffset: PropTypes.oneOfType([
-    PropTypes.number,
-    PropTypes.shape({
-      x: PropTypes.number,
-      y: PropTypes.number,
-    }),
-  ]),
-  events: PropTypes.array,
-  selected: PropTypes.object,
-
   accessors: PropTypes.object.isRequired,
-  components: PropTypes.object.isRequired,
   getters: PropTypes.object.isRequired,
+  selected: PropTypes.object,
+  components: PropTypes.object.isRequired,
   localizer: PropTypes.object.isRequired,
+  position: PropTypes.object.isRequired,
+  show: PropTypes.func.isRequired,
+  events: PropTypes.array.isRequired,
+  slotStart: PropTypes.instanceOf(Date).isRequired,
+  slotEnd: PropTypes.instanceOf(Date),
   onSelect: PropTypes.func,
   onDoubleClick: PropTypes.func,
   onKeyPress: PropTypes.func,
   handleDragStart: PropTypes.func,
-  show: PropTypes.func,
-  slotStart: PropTypes.instanceOf(Date),
-  slotEnd: PropTypes.number,
-  popperRef: PropTypes.oneOfType([
-    PropTypes.func,
-    PropTypes.shape({ current: PropTypes.Element }),
-  ]),
+  style: PropTypes.object,
+  offset: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
 }
-
-/**
- * The Overlay component, of react-overlays, creates a ref that is passed to the Popup, and
- * requires proper ref forwarding to be used without error
- */
-export default React.forwardRef((props, ref) => (
-  <Popup popperRef={ref} {...props} />
-))
+export default Popup
diff --git a/src/hooks/useClickOutside.js b/src/hooks/useClickOutside.js
new file mode 100644
index 0000000000..e25e0a6515
--- /dev/null
+++ b/src/hooks/useClickOutside.js
@@ -0,0 +1,15 @@
+import { useEffect } from 'react'
+
+export default function useClickOutside({ ref, callback }) {
+  useEffect(() => {
+    const handleClickOutside = (e) => {
+      if (ref.current && !ref.current.contains(e.target)) {
+        callback()
+      }
+    }
+    document.addEventListener('mousedown', handleClickOutside)
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside)
+    }
+  }, [ref, callback])
+}
diff --git a/yarn.lock b/yarn.lock
index f5e3b07017..84cf95982b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1863,14 +1863,14 @@
     pirates "^4.0.5"
     source-map-support "^0.5.16"
 
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
   version "7.17.2"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
   integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
   dependencies:
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6":
+"@babel/runtime@^7.13.8", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6":
   version "7.18.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580"
   integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==
@@ -2803,15 +2803,15 @@
     schema-utils "^3.0.0"
     source-map "^0.7.3"
 
-"@popperjs/core@^2.5.3":
-  version "2.11.2"
-  resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9"
-  integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==
+"@popperjs/core@^2.8.6":
+  version "2.11.5"
+  resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
+  integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
 
-"@restart/hooks@^0.3.25":
-  version "0.3.27"
-  resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.3.27.tgz#91f356d66d4699a8cd8b3d008402708b6a9dc505"
-  integrity sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==
+"@restart/hooks@^0.4.7":
+  version "0.4.7"
+  resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.7.tgz#d79ca6472c01ce04389fc73d4a79af1b5e33cd39"
+  integrity sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A==
   dependencies:
     dequal "^2.0.2"
 
@@ -13022,18 +13022,18 @@ react-lifecycles-compat@^3.0.4:
   resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
   integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
 
-react-overlays@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-4.1.1.tgz#0060107cbe1c5171a744ccda3fbf0556d064bc5f"
-  integrity sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==
+react-overlays@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-5.2.0.tgz#e7ebfdfdfbebd9d23cafd0bc2cac1d08abf1535b"
+  integrity sha512-dKZR/w6qeAsW0z0aIlwq/5H/M6o5T4RSlPnqIKqYVJ++rjoPSFcVggPhDWno8awZQsuMMtkjuksTbE8vOY0s9g==
   dependencies:
-    "@babel/runtime" "^7.12.1"
-    "@popperjs/core" "^2.5.3"
-    "@restart/hooks" "^0.3.25"
+    "@babel/runtime" "^7.13.8"
+    "@popperjs/core" "^2.8.6"
+    "@restart/hooks" "^0.4.7"
     "@types/warning" "^3.0.0"
     dom-helpers "^5.2.0"
     prop-types "^15.7.2"
-    uncontrollable "^7.0.0"
+    uncontrollable "^7.2.1"
     warning "^4.0.3"
 
 react-refresh@^0.11.0:
@@ -15065,7 +15065,7 @@ unbox-primitive@^1.0.2:
     has-symbols "^1.0.3"
     which-boxed-primitive "^1.0.2"
 
-uncontrollable@^7.0.0, uncontrollable@^7.2.1:
+uncontrollable@^7.2.1:
   version "7.2.1"
   resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738"
   integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==