ReactJS:哪种方法最适合存储通过 useRef 引用的 HTML canvas 元素的参数?

ReactJS: Which method is best to store parameters of a HTML canvas element, referenced through useRef?

我正在创建一个涉及在 HTML canvas 元素上绘制的 React 应用程序,定义如下:

function TestElement(props) {
  const canvas = useRef(null);

  return (
    <canvas className='visualizer' ref={canvas} />
  );
}

为了在绘图时访问 canvas 高度或宽度之类的东西,我在 useEffect 挂钩中设置了一些 vars

var center_x;
var center_y;
// etc...

useEffect( () => {
  if (canvas != null) {
    center_x = canvas.current.width / 2;
    center_y = canvas.current.height / 2;
    // etc...
  }
}, [canvas]);

然而,eslint 给出以下警告:

Assignments to the 'center_x' variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect.eslintreact-hooks/exhaustive-deps

但是,这个值不应该在渲染之间保留吗?因为有可能在渲染之间 canvas 的 size/shape 更改导致必须重置它?我正处于可以使用多种方法存储这些值的十字路口:

但我不确定该使用哪个。而且因为性能很重要,所以我不想选择可能导致不必要的开销和性能影响的一个。 我应该使用这三种方法中的哪一种来存储 canvas 的参数以获得最佳性能和行为(经常绘制到 canvas)? 我应该听eslint,还是可以使用 vars?

我对反应有点陌生,所以我很感激任何指导。谢谢。

canvas.current 放入 useEffect() 的依赖数组中是一种反模式,您会收到警告:

Mutable values like 'canvas.current' aren't valid dependencies because mutating them doesn't re-render the component.

正如 Vitali Zaidman 的 this article 指出的那样,“当使用 useRef 挂载(卸载)组件并附加到 ref.current 时,没有回调或重新渲染”。你要用的其实是useCallback()。当 useCallback() 返回最新的 canvas DOM 引用时,您可以通过设置 centerXcenterY 来做出反应。正如您所建议的,您可以使用 useState().

跟踪这些变量作为状态
const [centerX, setCenterX] = useState(null);
const [centerY, setCenterY] = useState(null);

const canvasRef = useCallback((canvasNode) => {
  setCenterX(canvasNode.width / 2);
  setCenterY(canvasNode.height / 2);
}, []);

...

return (<canvas ref={canvasRef} />);