React.memo
首先我们先来了解一下 React.memo
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [n,setN] = useState(0)
const [m,setM] = useState(0)
const addN=()=>{
setN(i=>i+1)
}
const addM=()=>{
setM(i=>i+1)
}
return (
<div className="App">
<h1>n:{n}</h1>
<Child value={m}/>
<button onClick={addN}>n+1</button>
<button onClick={addM}>m+1</button>
</div>
);
}
const Child =(props)=> {
console.log('Child 执行了')
return <h1>m:{props.value}</h1>;
}
效果
例子中,当 n
和 m
变化时,因为<App>
重新渲染, 所以Child
函数重新执行,使用 React.memo
我们再来看看
import React, { useState } from "react";
import "./styles.css";
export default function App() {/*其他代码*/}
const Child =React.memo((props)=> {
console.log('Child 执行了')
return <h1>m:{props.value}</h1>;
});
效果
可以看出,当
n
变化时函数 Child
没有执行,而当 m
变化时,函数 Child
执行了,因此,我们可以把props没有改变的而执行的函数放入React.memo
中,可以优化组件,解决函数重复执行,降低效率问题
但是,React.memo
有一个 bug,我们来看下面的例子
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [n,setN] = useState(0)
const [m,setM] = useState(0)
const addN=()=>{
setN(i=>i+1)
}
const addM=()=>{
setM(i=>i+1)
}
const ClickChild=()=>{}
return (
<div className="App">
<h1>n:{n}</h1>
<Child value={m} onClick={ClickChild}/>
<button onClick={addN}>n+1</button>
<button onClick={addM}>m+1</button>
</div>
);
}
const Child =React.memo((props)=> {
console.log('Child 执行了')
return <h1 onClick={props.onClick}>m:{props.value}</h1>;
});
效果
可以看到,当n
变化时函数 Child
又执行了,这是为什么呢?原因是:当 <App>
重新渲染,const ClickChild=()=>{}
重新执行,于是 ClickChild
的地址已经和上一次的不同了,因此函数 Child
执行了
于是我们就需要用到 useMemo
了,
useMemo
useMemo
的第一个函数是 ()=>value
,第二个参数是依赖 [m]
,该 Hook 可以缓存函数的返回值,避免函数不必要的调用,导致组件的重新渲染
/*其他代码*/
const ClickChild=useMemo(()=>{
return ()=>{}
},[m])
/*其他代码*/
效果
注意: 如果你的
value
是一个函数的话,则要写成useMome(()=>x=>coonsole.log(x),[m])
,由于太难用,于是就有了语法糖useCallback
,即可以改写成useCallback(x=>coonsole.log(x),[m])