React.memo
作用:允许组件在props没有改变的情况下跳过重新渲染
组件默认的渲染机制
默认机制:顶层组件发生重新渲染,这个组件树的子级组件都会被重新渲染
jsx
// memo
// 作用:允许组件在props没有改变的情况下跳过重新渲染
import { useState } from 'react'
function Son() {
console.log('子组件被重新渲染了')
return <div>this is son</div>
}
function App() {
const [forceUpdate] = useState()
console.log('父组件重新渲染了')
return (
<Son />
<button onClick={() => forceUpdate(Math.random())}>update</button>
)
}
export default App
使用React.memo优化
缓存机制:只有props发生变化时才重新渲染
下面的子组件通过 memo 进行包裹之后,返回一个新的组件MemoSon, 只有传给MemoSon的props参数发生变化时才会重新渲染
jsx
import React, { useState } from 'react'
const MemoSon = React.memo(function Son() {
console.log('子组件被重新渲染了')
return <div>this is span</div>
})
function App() {
const [forceUpdate] = useState()
console.log('父组件重新渲染了')
return (
<MemoSon />
<button onClick={() => forceUpdate(Math.random())}>update</button>
)
}
export default App
props变化重新渲染
jsx
import React, { useState } from 'react'
const MemoSon = React.memo(function Son() {
console.log('子组件被重新渲染了')
return <div>this is span</div>
})
function App() {
console.log('父组件重新渲染了')
const [count, setCount] = useState(0)
return (
<MemoSon count={count} />
<button onClick={() => setCount(count + 1)}>+{count}</button>
)
}
export default App
props的比较机制
-
传递一个简单类型的prop prop变化时组件重新渲染
-
传递一个引用类型的prop 比较的是新值和旧值的引用是否相等 当父组件的函数重新执行时,实际上形成的是新的数组引用
对于props的比较,进行的是'浅比较',底层使用
Object.is
进行比较,针对于对象数据类型,只会对比俩次的引用是否相等,如果不相等就会重新渲染,React并不关心对象中的具体属性
jsx
import React, { useState } from 'react'
const MemoSon = React.memo(function Son() {
console.log('子组件被重新渲染了')
return <div>this is span</div>
})
function App() {
// const [count, setCount] = useState(0)
const [list, setList] = useState([1, 2, 3])
return (
<>
<MemoSon list={list} />
<button onClick={() => setList([1, 2, 3])}>
{JSON.stringify(list)}
</button>
</>
)
}
export default App
说明:虽然俩次的list状态都是 [1,2,3]
, 但是因为组件App俩次渲染生成了不同的对象引用list,所以传给MemoSon组件的props视为不同,子组件就会发生重新渲染
保证引用稳定 -> useMemo 组件渲染的过程中缓存一个值
javascript
import { memo, useMemo, useState } from 'react'
const MemoSon = memo(function Son ({ list }) {
console.log('子组件重新渲染了')
return <div>this is Son {list}</div>
})
function App () {
const [count, setCount] = useState(0)
const list = useMemo(() => {
return [1, 2, 3]
}, [])
return (
<div className="App">
<MemoSon list={list} />
<button onClick={() => setCount(count + 1)}>change Count</button>
</div>
)
}
export default App