当第三方库触发事件时,我如何告诉 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 以防止重新呈现。