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

useRef钩子无法及时更新的原因?用于状态设置与Emotion.js修改CSS

useRef 无法及时更新的原因及结合 Emotion.js 的解决方案

useRef 确实会出现“看起来没及时更新”的情况,核心和它的设计特性、你的使用方式直接相关,结合你用 Emotion.js 修改 CSS 的场景,具体拆解如下:

核心原因:useRef 的特性与使用误区

  • useRef 不触发组件重渲染:useRef 的 .current 属性是可变的,但它的更新不会触发组件重新渲染。如果你用它来管理需要驱动 UI(比如 Emotion 样式)的“状态”,组件不会因为 .current 变化而重新执行,依赖它的 CSS 自然不会同步更新。
    错误用法示例:

    const sizeRef = useRef(50);
    
    // 修改ref,但组件不重渲染
    const handleClick = () => {
      sizeRef.current += 50;
    };
    
    // Emotion的样式只会在组件初始渲染时计算一次,后续不会更新
    const boxStyle = css`
      width: ${sizeRef.current}px;
      height: ${sizeRef.current}px;
      background: blue;
    `;
    

    点击按钮后,sizeRef.current 确实变化了,但组件没重渲染,boxStyle 不会重新计算,样式毫无变化。

  • 更新时机与渲染周期不匹配:如果在组件渲染完成后的回调(比如 setTimeout、DOM 事件回调)里更新 useRef,此时组件已经完成渲染,依赖 useRef 的样式早已计算完毕,除非手动触发重渲染,否则样式不会同步。

结合 Emotion.js 的正确做法

1. 用 useState 管理驱动样式的状态

如果某个值需要同步影响 Emotion 的 CSS,优先用 useState 而非 useRef——useState 的更新会触发组件重渲染,让 Emotion 的 css 函数重新计算样式:

const [size, setSize] = useState(50);

const handleClick = () => {
  setSize(prev => prev + 50);
};

// 每次组件重渲染时,都会基于最新的size计算样式
const boxStyle = css`
  width: ${size}px;
  height: ${size}px;
  background: blue;
`;

2. 必须用 useRef 时,手动触发重渲染

如果场景确实需要用 useRef(比如存储 DOM 元素、无需频繁重渲染的可变值),但又要同步更新样式,可以搭配一个空的 useState 来强制触发重渲染:

const sizeRef = useRef(50);
const [, forceRender] = useState({});

const handleClick = () => {
  sizeRef.current += 50;
  // 通过更新一个空对象触发重渲染
  forceRender({});
};

// 重渲染时,会基于最新的sizeRef.current计算样式
const boxStyle = css`
  width: ${sizeRef.current}px;
  height: ${sizeRef.current}px;
  background: blue;
`;

关键提醒

Emotion 的 css 函数是在组件渲染阶段执行的,只有组件重渲染时,它才会重新计算样式。所以任何需要驱动样式的变量,都应该用能触发重渲染的状态管理方案(useState/useReducer),而非 useRef。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:50:23