Reputation: 4353
Consider two divs. One is the parent. One is the child. The child partially overlaps the parent.
If any area above the parent (even if it's blocked by the child) is clicked, I want to receive the offsetX for the parent.
However, since it doesn't appear to be possible as the onClick evenargs are always calculated for the most nested element, I decided to use the following workaround:
const addOnClickInfo = (e) => {
Object.assign(e, {customInfo: {startOfTimelineElementClicked: start}});
}
return <div onClick={addOnClickInfo} id='te' style={gridMemberStyle}></div>
const onClickHandler = e => {
console.log(e.customInfo); // IMPORTANT LINE
console.log(e.customInfo.startOfTimelineElementClicked); // IMPORTANT LINE
// Here, with startOfTimelineElementClicked we've got enough data to calculate offsetX for the parent.
};
First, is there some other, neater solution (getting eventargs for an element higher in DOM hierarchy than its child that is the actual event.target) to this problem?
Second: the data printed by console.log
s above is delayed by one click. As the site loads, e.customInfo
for the first click is undefined
. From the second click and on it does contain a value, however it's always the one for the previous click. How does it happen?
UPDATE: While the above is true, if we substitute console.log(e)
for console.log(customInfo)
, and inspect e
in Google DevTools, it does seem to contain customInfo
. Yet, a console.log(e.customInfo)
literally a line later is undefined
. Such as:
console.log(e) // Expanding it in Google DevTools; clearly has customInfo
console.log(e.customInfo) // undefined...?
Upvotes: 2
Views: 38
Reputation: 4353
Silly mistake, captured events are called before non-captured events, not the other way around. This solves this issue.
It probably explains the DevTools issue as well. It loads object data only once you expand the object to view its contents, and by the time I manage to expand it, the event has already finished its bubbling phase.
Upvotes: 0
Reputation: 21317
You could achieve the same effect by appending a ref
to your parent and pass down a function to retrieve the current offsetX
from the parent
const Parent = () =>{
const ref = useRef(null)
const getOffset = ref.current ? ref.current.offsetX : null
return(
<div ref={ref}>
<Child getOffset={getOffset} />
</div>
)
}
And inside your Child
const Child = ({ getOffset }) =>{
const [offset, setOffset] = useState(getOffset())
return (
<>
{`Current parent's offset: ${offset}`}
<button onClick={() => setOffset(getOffset())}>Refresh offset </button>
</>
)
}
Upvotes: 2