Memo
理解React.useMemo前要先理解React.Memo
先看代码:
import React from "react";
function App(){
const [n,setN] = React.useState(0);
const [m,setM] = React.useState(0);
const onClick = () => {
setN(n+1)
}
return (
<div>
<div>
<button onClick={onClick}>update n {n}</button>
</div>
<Child data={m}/>
</div>
)
}
function Child(props) {
console.log('child执行了');
return <div>
child: {props.data}
</div>
}
export default App
复制代码
渲染结果如下所示,点击按钮update n时,虽然child的值不影响,但是child组件里的log还是被打印出来了。
Child用React.memo(Child)代替就好了,代码如下:
import React from "react";
function App(){
const [n,setN] = React.useState(0);
const [m,setM] = React.useState(0);
const onClick = () => {
setN(n+1)
}
const onClick2 = () => {
setM(m+1)
}
return (
<div>
<div>
<button onClick={onClick}>update n {n}</button>
<button onClick={onClick2}>update m {m}</button>
</div>
<Child2 data={m}/>
</div>
)
}
function Child(props) {
console.log('child执行了');
return <div>
child: {props.data}
</div>
}
const Child2 = React.memo(Child)
export default App
复制代码
渲染结果如下,当m值改变后才会log
Memo的bug
当添加了监听函数之后,Child组件的log又执行了,代码如下:
import React from "react"
export default function App() {
console.log('app执行了');
const [n, setN] = React.useState(0);
const [m, setM] = React.useState(0);
const onClick = () => {
setN(n + 1);
};
const onClickChild = () => {
console.log(m);
};
return (
<div className="App">
<div>
<button onClick={onClick}>update n {n}</button>
</div>
<Child2 data={m} onClick={onClickChild} />
{/* Child2 居然又执行了 */}
</div>
);
}
function Child(props) {
console.log("child 执行了");
return <div onClick={props.onClick}>child: {props.data}</div>;
}
const Child2 = React.memo(Child);
复制代码
渲染结果如下:
出现以上结果是因为,App运行时会再次执行onClickChild
,生成新的函数,新旧函数功能虽然一样,但是地址时不同的,那只能用useMemo了。
useMemo
useMemo的特点:
- 第一个参数是() => value
- 第二个参数是依赖[m,n]
- 只有依赖变化时,才会计算除新的value
- 如果依赖不变,就会重用之前的value
有没有很像Vue2中的computed?
通过useMemo改动上面的例子:
import React from "react"
export default function App() {
const [n, setN] = React.useState(0);
const [m, setM] = React.useState(0);
const onClick = () => {
setN(n + 1);
};
const onClickChild = React.useMemo(()=>{
return ()=>{
console.log(m);
}
},[m])
return (
<div className="App">
<div>
<button onClick={onClick}>update n {n}</button>
</div>
<Child2 data={m} onClick={onClickChild} />
</div>
);
}
function Child(props) {
console.log("child 执行了");
return <div onClick={props.onClick}>child: {props.data}</div>;
}
const Child2 = React.memo(Child);
复制代码
渲染结果如下,只有m变化了才会触发Child组件log
useCallback
在useMemo中,如果value是个函数,那么就要写成useMemo(()=>(x)=>console.log(x))
,这是一个返回函数的函数,有点难用,于是就出现了useCallback
useCallback与useMemo是等价的,用法不同,如:
useCallback(x=>log(x),[m])
等价于 useMemo(()=>x=>log(x),[m])
用useCallback改写以上例子:
import React from "react"
export default function App() {
const [n, setN] = React.useState(0);
const [m, setM] = React.useState(0);
const onClick = () => {
setN(n + 1);
};
const onClickChild = React.useeCallback(()=>{
console.log(m);
},[m])
return (
<div className="App">
<div>
<button onClick={onClick}>update n {n}</button>
</div>
<Child2 data={m} onClick={onClickChild} />
</div>
);
}
function Child(props) {
console.log("child 执行了");
return <div onClick={props.onClick}>child: {props.data}</div>;
}
const Child2 = React.memo(Child);
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END