I am using createjs
to create an canvas, and there is a double click event in this canvas, now I want to tell a React component when the event is triggered, and set state to a variable that defined in the custom function. for example, I want to set the value to 'pose.position' that's in the custom function.
my react component:
const [value, setValue] = useState(null);
const handleEvent = event => {
console.log(value);
};
useEffect(() => {
const ros = new ROSLIB.Ros({
url
});
const viewer = new ROS2D.Viewer({
divID,
width,
height
});
const nav = NAV2D.OccupancyGridClientNav({
ros,
rootObject: viewer.scene,
viewer,
serverName,
continuous
});
setValue(nav.position);
const canvas = divEl.current.children[0];
canvas.addEventListener("dblclick", handleEvent, false);
return () => {
canvas.removeEventListener("dblclick", handleEvnet);
};
}, []);
return <div id={divID} ref={divEl} />;
and the custom function:
this.rootObject.addEventListener("dblclick", function(event) {
// convert to ROS coordinates
const coords = stage.globalToRos(event.stageX, event.stageY);
const pose = new ROSLIB.Pose({
position: new ROSLIB.Vector3(coords)
});
// send the goal
sendGoal(pose);
that.position = pose.position;
// that.mouseClick = true;
console.log("clicked");
});
//I do not know how my React component can get this value, so I just return
return this.position;
The problem is the value in component only set once,and the log function in handleEvent outputs null, the value will not be updated.How do I notify React that the value is changed? Should I create another useEffect(()=>{}, [value])
?
OR
Can I dispatch an action in this.rootObject.addEventListener
so I can notify react to re-render some components? Can I use redux in non-react function?
From what I see there are 2 options to get this working:
1) Put the part that calculates position
to the React component:
const [value, setValue] = useState(null);
const handleEvent = event => {
// convert to ROS coordinates
const coords = stage.globalToRos(event.stageX, event.stageY);
const pose = new ROSLIB.Pose({
position: new ROSLIB.Vector3(coords)
});
setValue(pose.position);
};
2) Introduce an extra event and listen for it in the component. So that your custom function will look something like this:
this.rootObject.addEventListener("dblclick", function(event) {
// convert to ROS coordinates
const coords = stage.globalToRos(event.stageX, event.stageY);
const pose = new ROSLIB.Pose({
position: new ROSLIB.Vector3(coords)
});
// send the goal
sendGoal(pose);
this.dispatchEvent(new CustomEvent('newposition', { detail: pose.position }));
}
and then add an extra line in your React component:
canvas.addEventListener("newposition", (e) => setValue(e.detail), false);
In both cases, you will need to add value
as a second argument to useEffect
to prevent re-renders.