为何调用空回调的React setTransition()会引发两次重渲染?
为什么调用无状态更新的setTransition会触发两次组件重渲染?
点击Save按钮时,会调用setTransition(() => {})但其中无任何状态更新逻辑,按预期不应触发组件重渲染。然而实际点击后,控制台却出现两次“rendering”日志,这一现象的原因是什么?
相关代码
import React, {useState, useRef, useEffect, useTransition} from 'react'; function Item({name, _key}) { const [isPending, setTransition] = useTransition(); const [updatingName, setUpdatingName] = useState(false); const nameInputElement = useRef(); useEffect(() => { if (updatingName) { nameInputElement.current.focus(); } }, [updatingName]); function onUpdateClick() { setUpdatingName(true); } function onCancelClick() { setUpdatingName(false); } console.log('rendering'); return ( <div> <input ref={nameInputElement} type="text" defaultValue={name} name="name" disabled={!updatingName} /> {!updatingName ? <> <button key={1} type="button" onClick={onUpdateClick}>Update</button> <button key={2} type="submit" name="delete" value={_key}>Remove</button> </> : <> <button key={3} type="button" name="update" onClick={(e) => { setTransition(() => {}) }}>Save</button> <button key={4} type="button" onClick={onCancelClick}>Cancel</button> </>} </div> ) } function ItemList({title}) { return <> <h1>{title}</h1> <form method="post" onSubmit={(e) => {e.preventDefault()}}> <Item name={'small'} _key={0}></Item> </form> </> } export default ItemList;
原因分析
这是useTransition的内置机制导致的:
- 当调用
setTransition时,React会立即将useTransition返回的isPending状态设为true,触发第一次组件重渲染,用来标记过渡操作的开始。 - 随后React会执行你传入的回调函数(这里是空函数),回调执行完成后,React会将
isPending设为false,触发第二次重渲染,标记过渡操作的结束。
哪怕你的回调函数里没有任何状态更新逻辑,useTransition也会完成这个“启动过渡-结束过渡”的完整流程,因此会触发两次重渲染。
内容的提问来源于stack exchange,提问作者coderboy
相关产品推荐
相关产品推荐

