Blackcell's Blog

React:什么时候该用 state?分清你要的到底是什么状态

React  ·  

很多人写 React 会随手就写 useState,但你真的分清:这个变量,是否需要驱动 UI 更新?

业务需求

点击按钮,累计点击次数,点击≥5 次之后,展示组件期间的 render 次数。

注意:页面并不需要展示点击次数本身,只需要在达到阈值后触发展示逻辑。

直觉写法:直接用 useState

很多人第一反应,点击次数是变化的数据,直接上 useState。

const [count, setCount] = useState(0);
const [showRender, setShowRender] = useState(false);

function handleClick() {
  setCount(count + 1);
  if(count >=5) {
    setShowRender(true);
  }
}

return (

<div>
    {/* 
<div>点击了 {count} 次</div> */}
    <button onClick={handleClick}>点击</button>
    { showRender && 
<div>展示render次数</div> }
  </div>
)

一开始我们会把 count 渲染到页面上:点击了 {count} 次,此时 count 要驱动界面显示,用 useState 完全合理。

但需求变更:不需要页面显示点击次数,只拿它做内部判断条件。于是我们把渲染 count 的 div 注释 / 删掉。

问题来了:count 依旧是 state,每次 setCount 都会触发组件重新渲染。 即便页面完全不需要显示 count,每点一次按钮,组件都会执行一次 render,直到满足大于等于 5 次条件。

核心思考:这个变量和 UI 还有关系吗?

当我们删掉展示 count 的 DOM 之后:状态变量和 UI 之间的关联被切断了。

useState 的本质:变量变化,触发组件重渲染,更新界面。 如果一个数据变化,不需要改变页面上任何 DOM,仅仅用于业务逻辑判断、做计数、存临时实例,那就不该放在 state 里。

这种只需要 “记住一个值,不驱动界面更新” 的数据,应该交给 useRef。

使用 useRef 重构

const clickCountRef = useRef(0);
const [showRender, setShowRender] = useState(false);

const handleClick = () => {
  clickCountRef.current += 1;
  // ref修改不会触发重渲染
  if (clickCountRef.current >= 5) {
    setShowRender(true);
  }
};

return (

<div>
    <button onClick={handleClick}>点击</button>
    {showRender && 
<div>展示render次数</div>}
  </div>
);

效果完全一致,但是性能发生变化: 点击 1‑4 次的时候,修改 ref.current 不会触发组件重渲染; 直到第 5 次,执行 setShowRender,才会触发唯一一次渲染。

useState 和 useRef 的简单区分口诀

  1. ✅ 用 useState:变量改变 → 页面 UI 需要跟着变化。值变化需要刷新视图。
  2. ✅ 用 useRef:变量只做内部记忆,变化不需要更新界面;存定时器 id、DOM 实例、计数器、临时标记。

最终结论

写组件的时候,先区分变与不变:

如果一份数据不再影响 UI 渲染,就不要再继续占用 state,优先考虑切换为 ref。 state 是为界面渲染服务的,不是所有会变的数据,都要写成 state。


补充小提醒

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注