useCallback / useMemo:回调函数
useMemo和useCallback接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数,这个回调函数是经过处理后的也就是说父组件传递一个函数给子组件的时候,由于是无状态组件每一次都会重新生成新的props函数,这样就使得每一次传递给子组件的函数都发生了变化,这时候就会触发子组件的更新,这些更新是没有必要的,此时我们就可以通过usecallback来处理此函数,然后作为props传递给子组件
//父组件:
const A = () => {
return (
// 如果不使用useCallback包裹的话,每次A的更新,都会重新声明这个handleClick的这个函数,导致B组件无效的更新
// <B handleClick={ useCallback( () => doSomething,[x,xx]) };
)
}
//子组件B:
const B = (props) => {
const { handleClick } = props
return <div onClick={ handleClick }>我是子组件B</div>
}
不要把所有的方法都包上 useCallback,下面仔细讲
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const handleClickButton1 = () => {
setCount1(count1 + 1)
};
const handleClickButton2 = useCallback(() => {
setCount2(count2 + 1)
}, [count2]);
return (
<>
<button onClick={handleClickButton1}>button1</button>
<button onClick={handleClickButton2}>button2</button>
</>
)
上面这种写法在当前组件重新渲染时会声明一个新的 `handleClickButton1` 函数,下面 `useCallback` 里面的函数也会声明一个新的函数,被传入到 `useCallback` 中,尽管这个函数有可能因为 `inputs` 没有发生改变不会被返回到 `handleClickButton2` 变量上。
那么在我们这种情况它返回新的函数和老的函数也都一样,因为下面 `<button>` 已经都会被渲染一下,反而使用 `useCallback` 后每次执行到这里内部要要比对 `inputs` 是否变化,还有存一下之前的函数,消耗更大了。
来源:https://juejin.cn/post/6844904101445124110#heading-4
useCallback 是要配合子组件的 shouldComponentUpdate 或者 React.memo 一起来使用的,否则就是反向优化。
React.memo使用
在线代码:codesandbox.io/s/brave-cor…
子组件
import React from "react";
export interface OneProps {
data?: { a: number; b: number };
}
const B: React.FC<OneProps> = (props) => {
console.log("B组件更新了");
return (
<div style={{border: "1px solid red"}}>
这是B组件(儿子):
</div>
);
};
// export default B;
export default React.memo(B);
APP文件
import One from "./B";
import React, { useState } from "react";
const App = () => {
console.log("App组件更新");
const [data, setData] = useState("没有改变之前");
const [oneData] = useState({ a: 1, b: 2 });
return (
<div className="App">
<div>
<button onClick={() => setData("改变之后")}>改变APP内数据</button>
</div>
<div style={{border: "1px solid skyblue"}}>
App组件(爸爸):
<p>data: {data}</p>
</div>
{/* One组件 */}
<One data={oneData} />
</div>
);
};
export default App;
useRef
作用: 保存临时的变量,
const tem = useRef(null)
使用: tem = dom.current,current是当前的DOM