React中点击同按钮修改状态为何仅触发两次日志打印?
React useState 重复点击同按钮的打印行为解析
核心逻辑:React 的状态更新浅比较机制
React 的 useState 更新状态时,会对新值和当前值做严格浅比较(字符串这类原始值就是 === 判断):
- 若新旧值相等,React 会直接跳过组件重新渲染,组件内部的代码(包括你写的
console.log(resourceType))不会执行。 - 若新旧值不等,才会触发组件渲染,执行组件内的所有代码,包括打印当前状态。
你的场景拆解
初始状态是 resourceType = 'post',拿点击「User」按钮的流程举例:
- 第一次点User:状态从
'post'变'user',值不等 → 组件渲染 → 控制台打印user(第一次)。 - 第二次点User:调用
setResourceType('user'),新值和当前状态完全一致,但开发模式下 React 会做一次额外的验证性渲染,导致代码再执行一次,打印第二次user。这次渲染后 React 确认状态无变化,后续再点同按钮就会跳过渲染。 - 后续点击:因新旧状态完全相等,React 直接跳过渲染,不再打印。
验证组件是否真的渲染
你可以加个渲染日志,直观确认渲染触发情况:
import { useState, useEffect } from 'react'; export default function Hello() { const [resourceType, setResourceType] = useState('post'); // 每次渲染都会执行 useEffect(() => { console.log('组件重新渲染了'); }); console.log(resourceType); return ( <div> <button onClick={() => setResourceType('post')}>Post</button> <button onClick={() => setResourceType('user')}>User</button> <button onClick={() => setResourceType('comment')}>Comments</button> <h1>{resourceType}</h1> </div> ); }
运行后你会发现:连续点同按钮到第三次及以后,组件重新渲染了 的日志不会再出现,说明 React 确实跳过了渲染。
优化打印逻辑(只在状态变化时打印)
如果只想在状态真正变化时打印,把打印逻辑放到 useEffect 里,监听 resourceType:
import { useState, useEffect } from 'react'; export default function Hello() { const [resourceType, setResourceType] = useState('post'); // 仅当resourceType变化时执行 useEffect(() => { console.log(resourceType); }, [resourceType]); return ( <div> <button onClick={() => setResourceType('post')}>Post</button> <button onClick={() => setResourceType('user')}>User</button> <button onClick={() => setResourceType('comment')}>Comments</button> <h1>{resourceType}</h1> </div> ); }
这样无论点多少次同按钮,只有状态切换时才会打印一次。
内容的提问来源于stack exchange,提问作者Prashant Singh
相关产品推荐
相关产品推荐

