React.memo
作用:允许组件在props没有改变的情况下跳过重新渲染
组件默认的渲染机制
默认机制:顶层组件发生重新渲染,这个组件树的子级组件都会被重新渲染
// 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参数发生变化时才会重新渲染
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变化重新渲染
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并不关心对象中的具体属性
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 组件渲染的过程中缓存一个值
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