useCallBack(fn,deps)
const handleCount1 = useCallback(() => {
setCount1(count1+1);
},[count1]);
- return fn
- useCallBack需要配合React.memo使用
- useCallBack缓存的是函数地址,如果依赖的数据改变了,会返回一个新的内存地址,否则把旧函数内存地址返回;在子组件中需要使用memo检测props数据栈中内存地址是否有变化,如果栈地址改变,意味着useCallBack返回了新函数地址,那么子组件就会重新渲染。注意:useCallBack只是监听数据的内存地址是否发生变化,并不能防止组件的渲染。
parent.jsx
import React, {useCallback, useContext, useState} from "react";
import Child from "./child";
const Parent = () => {
const [count,setCount] = useState(1)
const handleShow = () => {
console.log("传入子组件的函数")
}
return (
<div>
<button onClick={() => setCount(count+1)}>{count}</button>
<Child show={handleShow}></Child>
</div>
)
}
export default Parent
child.jsx
```jsx
import React from "react";
const Child = React.memo(() => {
console.log("子组件重新渲染了")
return (
<div>子组件</div>
)
})
export default Child
点击button时,子组件也会重新渲染。当父组件渲染的时候,会重新构建所有的函数,销毁旧函数,memo会因为props中的函数内存地址每次都变化来重新渲染子组件。
子组件怎样才不更新?
import React, {useCallback, useContext, useState} from "react";
import Child from "./child";
const Parent = () => {
const [count,setCount] = useState(1)
//使用 useCallback
const handleShow = useCallback(() => {
console.log("传入子组件的函数")
},[])
return (
<div>
<button onClick={() => setCount(count+1)}>{count}</button>
<Child show={handleShow}></Child>
</div>
)
}
export default Parent
点击button,子组件不会重新渲染,控制台只在初始渲染时输出了一次;子组件没有重复渲染
useMemo(() => fn,deps)
useMemo(() => {
setCount2(count2+1)
},[count2]);
-
return value
-
useCallBack(fn,[deps]) 等价于 useMemo(() => fn,[deps])
-
每一个在callback中出现的值都应该作为deps useCallBack useMemo 会对依赖的数据以及返回值进行缓存,只有依赖改变的时候才会重新执行,否则就使用缓存。
-
使用场景: 当父组件传递给子组件方法或数据时,只要父组件一改变,其子组件也会重新渲染,而渲染是很消耗性能的,因此可以给传递给子组件的方法使用useCallBack,给传递给子组件的数据使用useMemo,但还是要适当的使用。
useState的疑惑
很多时候改变了状态数据的值,但却获取不到最新的值,总是感觉慢一拍。这是由于使用hooks,状态数据的改变是异步的,不能改变数据之后就立即获取到数据的值,因此,可以通过useEffect依赖状态数据,当数据改变时,获取到最新的值。
import React, {useState, useCallback, useMemo, useTransition, useEffect} from "react";
const TestHooks = () => {
const [count1,setCount1] = useState(1)
const [count2,setCount2] = useState(1)
const [count3,setCount3] = useState(1)
const handleCount1 = useCallback(() => {
setCount1(count1+1)
console.log(" handleCount1 count1",count1)
},[count1]);
const handleCount3 = () => {
setCount3(count3+1)
console.log("handleCount3 count3",count3)
}
useEffect(() => {
console.log("count1,count2,count3",count1,count2,count3)
},[count1,count2,count3])
return (
<div>
<button onClick={handleCount1}>count1:{count1}</button>
<button onClick={() => {setCount2(count2+1); console.log("setCount2 count2",count2)}}>count2:{count2}</button>
<button onClick={handleCount3}>count3:{count3}</button>
</div>
)
}
export default TestHooks
上面的setCount2(count2+1)改变count2的值,但是后面的console.log并不会打印出count2最新的值,是上一次的值;使用useEffect依赖count2,可打印出count2最新的值。