何时用 useCallback 和 useMemo
先了解下Js数据类型方面的基础知识
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
true === true // true
false === false // true
1 === 1 // true
'a' === 'a' // true
{} === {} // false
[] === [] // false
() => {} === () => {} // false
const z = {}
z === z // true
// NOTE: React 用的是 Object.is, 和 ===非常相似
先来看看下面例子
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
function ParentComp() {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<SonComp />
</div>
);
}
function SonComp() {
console.log('render SonComp')
return <div>Son Comp</div>
}
export default ParentComp
这里显然父组件更新会导致子组件渲染
用上Mamo()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
import React, { useState, memo } from 'react';
function ParentComp() {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<MemoSonComp />
</div>
);
}
const MemoSonComp = memo(function SonComp() {
console.log('render SonComp')
return <div>Son Comp</div>
})
此时子组件就不在被渲染
上面的例子并不能说明什么,因为SonComp是个纯组件。
接下来再来看看下面列子,我们给SonComp传个函数和一般的属性
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
import React, { useState, memo } from 'react';
function ParentComp() {
const [count, setCount] = useState(0)
const [name, setName] = useState('bob')
const increment = () => setCount(count + 1)
const changeName = (newName) => setName(newName) // 父组件渲染时会创建一个新的函数 相当于props变化了
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<MemoSonComp name={name} onClick={changeName} />
</div>
);
}
const MemoSonComp = memo(function SonComp({ name, onClick }) {
console.log('render SonComp')
return <>
<div>Son Comp ... {name}</div>
<button onClick={() => onClick('allen')}>改变 name 值</button>
</>
})
export default ParentComp
子组件又被渲染了
原因:父组件渲染时会创建一个新的函数 相当于props变化了,导致子组件渲染
useCallback()
这时useCallback就派上用场了
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
import React, { useState, memo,useCallback } from 'react';
function ParentComp() {
const [count, setCount] = useState(0)
const [name, setName] = useState('bob')
const increment = () => setCount(count + 1)
const changeName = useCallback((newName) => setName(newName), []) //包一层useCallback
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<MemoSonComp name={name} onClick={changeName} />
</div>
);
}
const MemoSonComp = memo(function SonComp({ name, onClick }) {
console.log('render SonComp')
return <>
<div>Son Comp ... {name}</div>
<button onClick={() => onClick('allen')}>改变 name 值</button>
</>
})
export default ParentComp
此时点击父组件按钮,控制台不会打印子组件被渲染的信息了。
原因:useCallback() 起到了缓存的作用,即便父组件渲染了,useCallback() 包裹的函数也不会重新生成,会返回上一次的函数引用。
useMemo()
再来看useMemo用途
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
import React, { useState, memo } from 'react';
function ParentComp() {
const [count, setCount] = useState(0)
const [name, setName] = useState('bob')
const [age, setAge] = useState(18)
const increment = () => setCount(count + 1)
const info = { name, age } //此处对象被新建,相当于props变化了
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<MemoSonComp info={info} />
</div>
);
}
const MemoSonComp = memo(function SonComp({ info }) {
console.log('render SonComp')
return <>
<div>Son Comp ... {info.name}</div>
</>
})
export default ParentComp
同样此处对象被新建,相当于props变化了,子组件被渲染
用上useMemo()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
import React, { useState, memo,useMemo } from 'react';
function ParentComp() {
const [count, setCount] = useState(0)
const [name, setName] = useState('bob')
const [age, setAge] = useState(18)
const increment = () => setCount(count + 1)
const info=useMemo(() => ({ name, age }), [name, age]) //此处对象被新建,相当于props变化了
return (
<div>
<button onClick={increment}>点击次数:{count}</button>
<MemoSonComp info={info} />
</div>
);
}
const MemoSonComp = memo(function SonComp({ info }) {
console.log('render SonComp')
return <>
<div>Son Comp ... {info.name}</div>
</>
})
export default ParentComp
子组件即可不被渲染
本文代码参考: https://www.jianshu.com/p/014ee0ebe959
(完)
0条看法
最新最后最热
等待你的评论