I'm trying to implement a modal using React where I want to position the modal relative to the element that triggered it (not the parent element). In this setup I can access a reference to the triggering element as you can see here
console.log(
"console button triggering modal offset" + event.target.offsetTop
);
But I can't access the reference to the schema, this code generates an error
useEffect(() => {
console.log("loggin ref width " + modalRef.current.offsetWidth);
}, [modalRef]);
I got this error message
Uncaught TypeError: Cannot read properties of undefined (reading 'offsetWidth')
at UserParamModal2.js:44:1
at commitHookEffectListMount (react-dom.development.js:23150:1)
at commitPassiveMountOnFiber (react-dom.development.js:24926:1)
at commitPassiveMountEffects_complete (react-dom.development.js:24891:1)
at commitPassiveMountEffects_begin (react-dom.development.js:24878:1)
at commitPassiveMountEffects (react-dom.development.js:24866:1)
at flushPassiveEffectsImpl (react-dom.development.js:27039:1)
at flushPassiveEffects (react-dom.development.js:26984:1)
When I remove the CSSTransition component, everything is fine, Here is the complete code. I would appreciate any help.
import {
React,
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
} from "react";
import ReactDOM from "react-dom";
import "./UserParamModal2.css";
import { CSSTransition } from "react-transition-group";
const UserParamModalOverlay = forwardRef((props, ref) => {
const content = (
<div className={`userparammodal ${props.className}`} ref={ref}>
{props.children}
</div>
);
return ReactDOM.createPortal(
content,
document.getElementById("modal-user-param")
);
});
const UserParamModal2 = forwardRef((props, ref) => {
const [visible, setVisible] = useState(false);
const modalRef = useRef();
useImperativeHandle(ref, () => {
return {
toggle(event) {
console.log(
"console button triggering modal offset" + event.target.offsetTop
);
setVisible((prev) => {
return !prev;
});
},
};
});
useEffect(() => {
console.log("loggin ref width " + modalRef.current.offsetWidth);
}, [modalRef]);
return (
<CSSTransition
in={visible}
mountOnEnter
unmountOnExit
timeout={200}
classNames="userparammodal"
>
<UserParamModalOverlay {...props} ref={modalRef}></UserParamModalOverlay>
</CSSTransition>
);
});
export default UserParamModal2;
You are getting the error because
modalRef.currentisundefinedthe first time you run useEffect. Just add a null check orif(modalRef.current)condition to avoid this error.If useEffect is not running, you may also need to update dependencies.
useEffect(() => { console.log("loggin ref width " + modalRef.current?.offsetWidth); }, [modalRef.current]);