i’am trying to implement à modal with React, in this modal i want to position the modal relatively to the the element wich trigger it (which is not à parent),
in this set up i can access the the reference to the triggering element like you see here
console.log(
"console button triggering modal offset" + event.target.offsetTop
);
but i can’t access the reference to the modal, this code generate an error
useEffect(() => {
console.log("loggin ref width " + modalRef.current.offsetWidth);
}, [modalRef]);
i have this erro 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 every thing is fine,
here is the full 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;
2
Answers
You are getting the error because
modalRef.current
isundefined
when useEffect runs for the first time. Just add null check orif(modalRef.current)
condition to avoid this error.You may also need to update the dependency if useEffect doesn’t run.
To assign that trigger modal to the element, you can use the useRef hook to get a reference to the triggering element and then calculate the state of the modal based on that reference Here is a general outline of how you can achieve this.
Get a reference to the triggering element: After defining the modal triggering element, in the parent component, use the useRef hook to create a ref for the triggering element.
Calculate the modal state: In the modal component, use the useEffect hook to calculate the state of the modal based on the state of the triggering element. You can use methods like getBoundingClientRect() to get the shape and location of the trigger object.
Use position styles: Set the position of the modal using inline styles or CSS classes based on calculated space.