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 引用时,您可以通过设置 centerX
和 centerY
来做出反应。正如您所建议的,您可以使用 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} />);
我正在创建一个涉及在 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 引用时,您可以通过设置 centerX
和 centerY
来做出反应。正如您所建议的,您可以使用 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} />);