You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需useState,React组件如何保留变量且不触发重渲染?

React函数组件中实现类似static的持久化变量方案

你需要的是React的useRef钩子,它刚好能满足你的需求:既不会触发组件重渲染,又能在组件多次重渲染之间保留变量值,相当于类组件中this上的实例属性,或者你说的static变量机制。

核心特性对比

  • 对比useState(你的test1):修改useRef的.current属性不会触发组件重渲染,避免了不必要的canvas重绘
  • 对比普通var/let变量(你的test2):组件每次重渲染时,useRef返回的对象都是同一个,存储在.current里的值会被持久保留,不会因为组件重渲染而重置

代码示例(ImagePreview组件)

import { useRef } from 'react';

function ImagePreview() {
  // 用useRef声明用于canvas绘制的点变量
  const point1 = useRef({ x: 0, y: 0 });
  const point2 = useRef({ x: 0, y: 0 });

  const updatePoint1 = (newX, newY) => {
    // 修改current属性,无重渲染触发
    point1.current = { x: newX, y: newY };
    // 直接调用canvas绘制逻辑
    drawPoints();
  };

  const updatePoint2 = (newX, newY) => {
    point2.current = { x: newX, y: newY };
    drawPoints();
  };

  const drawPoints = () => {
    const canvas = document.getElementById('preview-canvas');
    if (!canvas) return;
    
    const ctx = canvas.getContext('2d');
    // 清空画布后绘制两个点
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#ff0000';
    ctx.beginPath();
    ctx.arc(point1.current.x, point1.current.y, 6, 0, Math.PI * 2);
    ctx.fill();
    
    ctx.fillStyle = '#0000ff';
    ctx.beginPath();
    ctx.arc(point2.current.x, point2.current.y, 6, 0, Math.PI * 2);
    ctx.fill();
  };

  return (
    <canvas id="preview-canvas" width={600} height={400} />
  );
}

注意事项

  • useRef.current的变化不会触发组件重渲染,所以如果你的场景不需要依赖这些值更新React元素,完全适用;如果需要同步UI,那还是得结合useState
  • 不要在组件的render阶段直接修改useRef.current,建议在事件处理函数、useEffect等副作用钩子中修改

内容的提问来源于stack exchange,提问作者whitebear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:45:06