React Hooks如何避免状态变更时静态标题区域发生不必要重渲染?
问题原因
你当前所有UI都写在同一个组件内,只要组件内部的state发生更新,整个组件就会触发重渲染,和这个状态无关的title区域自然也会跟着重刷。
解决方法
有两种常用的实现方案,你可以根据自己的代码复杂度选择:
方案1:抽离独立组件 + React.memo 缓存(推荐)
把不需要重渲染的部分抽成独立组件,用React.memo包裹做浅比较缓存,只要组件的props没有变化,就不会触发重渲染。
如果同时抽离buttons和content组件,需要配合useCallback缓存事件函数,避免每次父组件渲染生成新的函数引用导致memo失效。
完整实现代码如下:
import { useState, memo, useCallback } from 'react' // 不变的标题组件,无props,缓存后永远不会重渲染 const Title = memo(() => { return ( <div className="title"> <h1>Title</h1> </div> ) }) // 按钮组件 const Buttons = memo(({ onClickOne, onClickTwo }) => { return ( <div className="buttons"> <button onClick={onClickOne}>1</button> <button onClick={onClickTwo}>2</button> </div> ) }) // 内容组件 const Content = memo(({ state }) => { return ( <div className="content"> {state === 0 ? <div>click!</div> : state === 1 ? <div>1</div> : <div> 2 </div>} </div> ) }) const Test = () => { const [state, setState] = useState(0) // 缓存事件函数,避免每次渲染生成新引用 const clickOne = useCallback(() => setState(1), []) const clickTwo = useCallback(() => setState(2), []) return ( <> <Title /> <Buttons onClickOne={clickOne} onClickTwo={clickTwo} /> <Content state={state} /> </> ) }
方案2:用useMemo直接缓存UI节点(适合不想拆分组件的场景)
如果不想拆分太多小组件,可以直接把不变的title节点用useMemo缓存,依赖项设为空数组,就不会随着state更新重新生成节点:
import { useState, useMemo } from 'react' const Test = () => { const [state, setState] = useState(0) const clickOne = () => setState(1) const clickTwo = () => setState(2) // 缓存标题节点,永远不更新 const titleNode = useMemo(() => ( <div className="title"> <h1>Title</h1> </div> ), []) return ( <> {titleNode} <div className="buttons"> <button onClick={clickOne}>1</button> <button onClick={clickTwo}>2</button> </div> <div className="content"> {state === 0 ? <div>click!</div> : state === 1 ? <div>1</div> : <div> 2 </div>} </div> </> ) }
内容的提问来源于stack exchange,提问作者sir0123
相关产品推荐
相关产品推荐

