昨天介绍了 useCallback 的基本使用方式。今天来介绍如何使用 useCallback 与 React.memo 来减少 render 次数。
首先,先来复习一下什麽情况下,会造成 re-render:
function Button({ count, increament }) {
console.log('%c Button component render', 'color: red')
return <button onClick={increament}>{count}</button>
}
function Description() {
console.log('%c Description render', 'color: green')
return <div>click the button</div>
}
function App() {
const [count, setCount] = React.useState(0)
const increament = () => {
setCount(count + 1)
}
console.log('%c App render', 'color: yellow')
return (
<div>
<Button count={count} increament={increament} />
<Description />
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
当我们 App 的 count state 改变时,会触发 re-render ,底下的元件不管有没有传递 props 或是 state 都会一起 re-render。
假设有个情况是我们需要 render list
function Button({ count, increament }) {
return <button onClick={increament}>{count}</button>
}
function MyList({ content, onClickHandler }) {
console.log(`${content} MyList render`)
return (
<div onClick={onClickHandler}>
{content}
</div>)
}
function App() {
const [count, setCount] = React.useState(0)
const [list, setList] = React.useState(['1', '2', '3', '4', '5'])
const increament = () => {
setCount(count + 1)
}
const clickItem = (e) => {
console.log(`click the ${e.target.textContent} item`)
}
console.log('%c App render', 'color: yellow')
return (
<div>
<Button count={count} increament={increament} />
{list.map(item => <MyList key={item} content={item} onClickHandler={clickItem} />)}
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
当我们点下按钮改变 count 时,我们的所有的 list item 都会 re-render,可以 count 改变跟 list 一点关系都没有。当我们这个 list 越来越多,render 也会增加,这样的情况就可以考虑使用 React.memo 将 MyList 元件包起来。
memo 这个是一个 HOC (High oreder component) ,接收一个元件并回传一个元件,这过程中 memo 跟 useCallback 很类似,它会去记住传进去的元件,并对照每一次 re-render 传进来的值是不是有改变,去决定要不要 re-render 。
所以使用 React.memo 将 MyList 包起来後,就会去比对 content 跟 onClickHandler 是不是有变化,有变化就 re-render 。
const MyList = React.memo(({ content, onClickHandler }) => {
console.log(`${content} MyList render`)
return (
<div onClick={onClickHandler}>
{content}
</div>)
})
这个时候当我们再次按下按钮改变 count state ,MyList 元件还是依然,re-render。为什麽呢?原因就是因为 onClickHandler 每一次都是新的实体。所以,这个时候就轮到 useCallback 登场了!
const clickItem = React.useCallback((e) => {
console.log(`click the ${e.target.textContent} item`)
}, [])
使用 useCallback 之後我们的 MyList 就不会因为 count 改变而 re-render 了!
以上是可以考虑使用 useCallback 的情境。
今天就先介绍到这边,如果有任何问题都欢迎在下方留言!
该文章同步发布於:我的部落格
<<: D24 / 什麽时候我的 Composable function 会重新被呼叫 - recompose
>>: Day 23 ATT&CK for ICS - Lateral Movement(1)
在我工作第三个月的时候,夥伴们觉得除错的方式能不能有所改善,於是有提出 EFK 架构,也就是 Ela...
watch监听器 监听data里面的值,当值有变化时,就会触发事件。 watch监听一个变数: &l...
其实RISC-V官方也有开发了一个instruction accurate等级的模拟器Spike,只...
Day23 的弹跳视窗元件,送出表单按钮在form标签的外面,理当来说form 外面的送出表单按钮和...
关於讯息伫列怎麽去储存呢?大致分成下列两种: 1.系统池(system pool):如果能确定讯息伫...