react 18 之 07之 hook的 useCallback和useMemo
- 函数式组件特性
- 1:函数式组件中,每一次更新状态,自定义的函数都要进行重新的声明和定义。
- 2:如果函数作为props传递给子组件,会造成子组件不必要的重新渲染:。问题点
- useCallback 进行性能优化,来实现子组件使用父组件的props中数据没有更新时重新渲染问题!
- useCallback 会为函数返回一个记忆的值,如果依赖的状态没有发生变化,那么则不会重新创建该函数,也就不会造成子组件不必要的重新渲染。
01:函数组件特性 ( 父组件向子组件传递一个函数的props时,父组件count更新渲染,导致子组件重新渲染)
code.jsx
import React, {
useState } from 'react';
import Son from "./Son"
export default function UseEffect(props) {
const [count,setCount] = useState(0)
console.log('我是父组件 rendered');
function addCount(){
setCount(count+1)
}
return (
<div className='content'>
<div>count - {
count} <button onClick={
addCount}>修改count</button></div>
<Son addCount={
addCount}></Son>
</div>
)
}
Son.jsx
import React from 'react';
export default function Son(props) {
const {
addCount } = props
console.log('我是Son rendered');
return (
<div className='content'>
Son组件 <button onClick={
addCount}>修改父组件的count</button>
</div>
)
}
useCallback特性 每一次渲染父组件的时候,子组件也重新更着渲染(造成性能的浪费)
02:解决上述函数组件特性:使用useCallback和React.memo实现子组件跟随使用的依赖而更新
code.jsx
import React, {
useCallback, useState } from 'react';
import Son from "./Son"
export default function UseEffect(props) {
const [count,setCount] = useState(0)
console.log('我是父组件 rendered');
const addCount = useCallback(()=>{
setCount((prevCount)=>prevCount+1)
},[])
return (
<div className='content'>
<div>count - {
count} <button onClick={
addCount}>修改count</button></div>
<Son addCount={
addCount} count={
count}></Son>
</div>
)
}
Son.jsx
import React from 'react';
const Son = React.memo((props)=>{
const {
addCount } = props
console.log('我是Son rendered');
return (
<div className='content'>
Son组件 <button onClick={
addCount}>修改父组件的count</button>
</div>
)
})
export default Son
效果
03:使得子组件重新渲染( 根据特定的值触发子组件的渲染 )
code.jsx
import React, {
useCallback, useState } from 'react';
import Son from "./Son"
export default function UseEffect(props) {
const [count,setCount] = useState(0)
console.log('我是父组件 rendered');
const addCount = useCallback(()=>{
setCount((prevCount)=>prevCount+1)
},[count])
return (
<div className='content'>
<div>count - {
count} <button onClick={
addCount}>修改count</button></div>
{
}
<Son addCount={
addCount}></Son>
</div>
)
}
Son.jsx
import React from 'react';
const Son = React.memo((props)=>{
const {
addCount } = props
console.log('我是Son rendered');
return (
<div className='content'>
Son组件 <button onClick={
addCount}>修改父组件的count</button>
</div>
)
})
export default Son
效果
04:useCallback基础
- 接受两个参数:回调函数和依赖数组
useCallback( ()=>{ // 写逻辑 eg: setCount( ( prevCount ) => prevCount + 1) } ,[] )
- 注意点:
- 当依赖数组中的任何一个值发生变化时,useCallback 将会返回一个新的回调函数,否则将会返回之前缓存的回调函数,这样可以避免在每次渲染时都重新生成回调函数,从而提高组件的性能