- 作者:老汪软件技巧
- 发表时间:2024-11-07 11:01
- 浏览量:53
useCallback
useCallback 与 useMemo 类似,它也是用于优化性能的。但是useCallback是用于缓存一个函数,让这个函数不会每次函数组件更新都会重新创建;而useMemo是用于缓存一个数据,让这个数据不会每次函数组件更新都会重新创建。useCallback会将传入的函数返回并缓存这个传入的函数,只有在依赖项发生变化的时候才会更新然后返回一个新的函数。这样当组件重新渲染时还是使用之前的函数,就不会被重新定义一次。定义函数组件的时候时常在函数体内定义一些内嵌函数,这些内嵌函数会在函数组件每次重新渲染时被重新定义,这可以用于避免在每次渲染时都创建新的函数实例。
useCallback产生原因的示例
import { useState, useEffect } from 'react'
function App() {
const Home = (props) => {
console.log(props,"Home 函数体运行了");
let [count, setCount] = useState(0);
let collect = () => {
console.log('收藏成功');
setCount(1);
};
useEffect(() => {
console.log('effect副作用函数运行');
}, [collect]);
return (
<div>
<p>{props.info.title}p>
<p>{props.info.singer}p>
<p>收藏数量:{count}p>
<button onClick={collect}>收藏button>
div>
)
}
let [arr, setArr] = useState([{ title: 'fly', singer: 'jessica' }, { title: 'city zoo', singer: 'G.E.M.' }]);
const add = () => {
let _arr = [...arr];
_arr.push({ title: 'sketch', singer: 'hyomin' });
setArr(_arr);
}
return (
<>
<h1>App组件h1>
<br />
<button onClick={add}>增加数据button>
<br />
<h2>Home组件h2>
{
arr.map((el, index) => {
return <Home info={el} key={index}>Home>
})
}
)
}
export default App
collect函数修改的状态是count,而useEffect监听的依赖项是collect函数。当页面初次加载后会创建collect函数,按理来说此时应该不会改变collect函数的引用地址,副作用函数不会运行。但是运行了代表在内存中创建了多个collect函数执行相同的业务这就影响了性能。因为执行useState返回的修改函数来修改状态就会让函数组件所有代码重新运行,这样每一次重新运行就会生成独立的作用域,重新创建新的collect函数。
语法和使用
import {useCallback} from "react"
const memoizedCallback = useCallback(callback, dependencies)
useCallback接收两个参数,第一个参数是需要被缓存的函数,第二个参数是这个函数的依赖项,只有依赖项数组里面的元素的值发生变化时useCallback才会返回新定义的函数,否则useCallback都会返回之前定义的函数。依赖项也可以是任何数据,它都会被监听。
关于useCallback第二个参数说明,和useEffect第二个参数同理:
import { useState, useEffect, useCallback } from 'react'
function App() {
const Home = (props) => {
console.log(props, "Home 函数体运行了");
let [count, setCount] = useState(0);
let collect = useCallback(() => {
console.log('收藏成功');
setCount(1);
}, []);
useEffect(() => {
console.log('effect副作用函数运行');
}, [collect]);
return (
<div>
<p>{props.info.title}p>
<p>{props.info.singer}p>
<p>收藏数量:{count}p>
<button onClick={collect}>收藏button>
div>
)
}
let [arr, setArr] = useState([{ title: 'fly', singer: 'jessica' }, { title: 'city zoo', singer: 'G.E.M.' }]);
const add = () => {
let _arr = [...arr];
_arr.push({ title: 'sketch', singer: 'hyomin' });
setArr(_arr);
}
return (
<>
<h1>App组件h1>
<br />
<button onClick={add}>增加数据button>
<br />
<h2>Home组件h2>
{
arr.map((el, index) => {
return <Home info={el} key={index}>Home>
})
}
)
}
export default App
依赖项是一个空数组,返回的函数只会在组件初次被渲染时会生成,useEffect的第一个参数函数没有运行,useEffect监听的函数地址没有发生变化,表示监听的函数没有被重新创建。
总结
当有一个函数作为事件处理程序时,它通常在创建后就不会改变。但是,如果直接在函数组件的函数体中定义这个函数,它会在函数组件每次渲染时被重新创建。useCallback解决的是防止函数组件里的不需要重复创建的函数被重复的重新创建。
useMemo解决的是:防止函数组件的函数体中的代码无效的被重复调用运行useCallback解决的是:防止函数组件的函数体中的函数无效的被重复创建