当第三方库触发事件时,我如何告诉 React 组件更改其状态?
How do I tell React component to change its state when an event is triggered from third party lib?
我正在使用createjs
创建一个canvas,并且在这个canvas中有一个双击事件,现在我想在事件触发时告诉一个React组件,并将状态设置为自定义函数中定义的变量。例如,我想将值设置为自定义函数中的 'pose.position'。
我的反应组件:
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} />;
和自定义函数:
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;
问题是component中的值只设置一次,handleEvent中的log函数输出null,不会是这个值updated.How我要通知React这个值改变了吗?我应该创建另一个 useEffect(()=>{}, [value])
吗?
或
我可以在 this.rootObject.addEventListener
中分派一个动作,以便通知 React 重新渲染某些组件吗?我可以在非反应函数中使用 redux 吗?
据我所知,有 2 个选项可以实现此功能:
1)将计算position
的部分放到React组件中:
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) 引入一个额外的事件并在组件中监听它。这样您的自定义函数将如下所示:
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 }));
}
然后在你的 React 组件中添加一行:
canvas.addEventListener("newposition", (e) => setValue(e.detail), false);
在这两种情况下,您都需要将 value
作为第二个参数添加到 useEffect
以防止重新呈现。
我正在使用createjs
创建一个canvas,并且在这个canvas中有一个双击事件,现在我想在事件触发时告诉一个React组件,并将状态设置为自定义函数中定义的变量。例如,我想将值设置为自定义函数中的 'pose.position'。
我的反应组件:
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} />;
和自定义函数:
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;
问题是component中的值只设置一次,handleEvent中的log函数输出null,不会是这个值updated.How我要通知React这个值改变了吗?我应该创建另一个 useEffect(()=>{}, [value])
吗?
或
我可以在 this.rootObject.addEventListener
中分派一个动作,以便通知 React 重新渲染某些组件吗?我可以在非反应函数中使用 redux 吗?
据我所知,有 2 个选项可以实现此功能:
1)将计算position
的部分放到React组件中:
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) 引入一个额外的事件并在组件中监听它。这样您的自定义函数将如下所示:
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 }));
}
然后在你的 React 组件中添加一行:
canvas.addEventListener("newposition", (e) => setValue(e.detail), false);
在这两种情况下,您都需要将 value
作为第二个参数添加到 useEffect
以防止重新呈现。