Im trying to listen click events on my react-three-fiber canvas. But Im getting a different event when using addEventListener
.
onClick
mesh property returns following event:
<mesh position={[0, 0, 0]} onClick={(e) => console.log('onClick mesh: ', e)}>
<boxGeometry attach="geometry" args={[10, 10, 10]} />
<meshStandardMaterial attach="material" color="hotpink" wireframe />
</mesh>
onClick mesh:
{dispatchConfig: Object, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: Object…}
// This is the event I need!!
And adding a event listener returns the following event:
const ThreeEventListener = () => {
const onClickDocument = (e) => {
console.log('onClick document listener: ', e)
}
useEffect(() => {
document.addEventListener('click', onClickDocument, false)
return () => document.removeEventListener('click', onClickDocument)
})
return null
}
onClick document listener:
MouseEvent {isTrusted: true, screenX: 1508, screenY: 427, clientX: 348, clientY: 178…}
// This is a normal DOM event from React that I dont need
Demo (Click the box to fire the events)
Im trying to listen click events on my react-three-fiber canvas. But Im getting a different event when using addEventListener
.
onClick
mesh property returns following event:
<mesh position={[0, 0, 0]} onClick={(e) => console.log('onClick mesh: ', e)}>
<boxGeometry attach="geometry" args={[10, 10, 10]} />
<meshStandardMaterial attach="material" color="hotpink" wireframe />
</mesh>
onClick mesh:
{dispatchConfig: Object, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: Object…}
// This is the event I need!!
And adding a event listener returns the following event:
const ThreeEventListener = () => {
const onClickDocument = (e) => {
console.log('onClick document listener: ', e)
}
useEffect(() => {
document.addEventListener('click', onClickDocument, false)
return () => document.removeEventListener('click', onClickDocument)
})
return null
}
onClick document listener:
MouseEvent {isTrusted: true, screenX: 1508, screenY: 427, clientX: 348, clientY: 178…}
// This is a normal DOM event from React that I dont need
Demo (Click the box to fire the events)
Share Improve this question asked Jan 10, 2021 at 20:02 RashomonRashomon 6,8124 gold badges39 silver badges80 bronze badges 1- Three does not have events, they e from R3F which watches for generic pointer events, raycasts then, and forms object level events. By adding event listeners to the canvas you'll just get regular pointer events again. Why are you doing this, though, in react you shouldn't touch the dom. – hpalu Commented Jan 11, 2021 at 8:19
2 Answers
Reset to default 3I assume what you got the first time is an instance of SyntheticEvent
that React uses as a wrapper over native events, bined with some useful for react-three-fiber fields - here's the doc. The doc says there's a native browser event and three.js useful data inside their event implementation (which is what you received).
I suggest taking out what you need out of the native event in the synthetic one:
event.nativeEvent
Here is a close solution using an external library called three.interaction
:
import { Interaction } from 'three.interaction'
const ThreeEventListener = () => {
useEffect(() => {
// init three.interaction on mount
const interaction = new Interaction(gl, scene, camera);
}, [])
const onClickScene = (event) => {
console.log('onClick scene listener: ', e)
}
useEffect(() => {
// attach callbacks to clicks thanks to three.interaction
scene.on('click', onClickScene)
return () => scene.on('click', () => {})
})
return null
}
The event created by three.interaction looks like:
onClick scene listener: InteractionEvent {stopped: false, target: Scene, currentTarget: Scene, type: "click", data: InteractionData, …}