React.useCallback(function,array)使用,React中的函数组件和类组件的取值(快照or最新值)

news/2024/11/16 12:30:45/

目录

React.useCallback(function,array)

React.memo

示例1

示例2

React中的函数组件和类组件的取值(快照or最新值)

闭包例子

修改React例子


React.useCallback(function,array)

返回一个函数,只有在array中的依赖项变化的时候才会更新(返回一个新的函数)。

使用场景:当父组件传入子组件函数时,由于React.memo进行的是浅比较,重新渲染时,函数的引用是发生改变的,所以会导致子组件重新渲染,而用useCallback后只要依赖的变量未发生改变将始终返回同一个函数引用,不会导致子组件重新渲染。

注意区别于useMemo 缓存的是函数的返回结果useCallback缓存的是函数

React.memo

React纯组件pureComponent、React.memo(FunComponent,compareFunction)、React.useMemo(callback,array)_YF-SOD的博客-CSDN博客

示例1

点击 Button1 的时候只会更新 Button1 和 Button3 后面的内容;

点击 Button2 会将三个按钮后的内容都更新;

点击 Button3 的也是只更新 Button1 和 Button3 后面的内容。

没有用useCallback包括的函数,每次都会重新声明一个新的方法,新的方法尽管和旧的方法一样,但是依旧是两个不同的对象,React.memo对比后发现对象props改变,就重新渲染了。而用uesCallback包括的函数只有当依赖项改变时才会返回新的函数(对象),所以不会重新渲染。

const Button = React.memo(({ onClickButton, children }) => {return (<><button onClick={onClickButton}>{children}</button><span>{Math.random()}</span></>);
});
export default function App() {const [count1, setCount1] = useState(0);const [count2, setCount2] = useState(0);const [count3, setCount3] = useState(0);const handleClickButton1 = () => {setCount1(count1 + 1);}const handleClickButton2 = useCallback(() => {setCount2(count2 + 1);}, [count2]);return (<div><div><Button onClickButton={handleClickButton1}>Button1</Button></div><div><Button onClickButton={handleClickButton2}>Button2</Button></div><div><Button  onClickButton={() => {setCount3(count3 + 1);     }}>Button3</Button></div></div>);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

示例2

useCallback - 简书

React中的函数组件和类组件的取值(快照or最新值)

下面先点击弹框按钮再点击double,alert中的数值,在类组件中始终显示的是最新的。而在函数组件中始终显示的是点击弹框时的数值(快照)而不是double后的数值。

import React, { useState } from "react";
class ClassProfilePage extends React.Component<any,any> {showMessage = () => {alert('Followed ' + this.props.user);};handleClick = () => {setTimeout(this.showMessage, 3000);};render() {return <button onClick={this.handleClick}>Follow</button>;}
}
function FunctionProfilePage(props) {const showMessage = () => {alert('Followed ' + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return (<button onClick={handleClick}>Follow</button>);
}
function App() {const [state,setState] = useState(1);return (<div className="App"><button onClick={() => {setState(x => x+x);}}>double</button><div>state:{state}</div><FunctionProfilePage user={state} /> // 点击始终显示的是快照值<ClassProfilePage user={state} /> // 点击始终显示的是最新值</div>);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

理解为在类组件中是挂载在this的引用上所以始终拿到的是最新的值,而在函数组件中是最新值。 

闭包例子

for(var i=0;i<10;i++){setTimeout(() => console.log('val:',i)) // 拿到的是最新值
}for(var i=0;i<10;i++){setTimeout(((val) => console.log('val:',val)).bind(null,i)); // 拿到的是快照
}const ref = {current: null}
for(var i=0;i<10;i++){ref.current = i; setTimeout(((val) => console.log('val:',ref.current)).bind(null,ref)); // 拿到的是最新值
}for (var i = 0; i < 10; i++) { // 拿到的是快照let t = i;setTimeout(() => {console.log("t:", t);});
}

修改React例子

可以通过下面修改在类组件中打印快照值。

  showMessage = (message) => {alert('Followed ' + message);};handleClick = () => {const message = this.props.user // 在触发异步函数之前保存快照setTimeout(()=>{this.showMessage(message)}, 3000);};

可以通过下面修改在函数组件中打印最新值(ref存取最新值)。

const ref = useRef("");
useEffect(() => {ref.current = props.user;
});
const showMessage = () => {console.log('ref:',ref)alert("Followed " + props.user +',' + ref.current);
};


http://www.ppmy.cn/news/17.html

相关文章

html实现ezuikit.js萤石云直播监控,ezuikit.js实时监控实现,萤石云实时监控简单实现

效果图 实现 下面的播放url获取&#xff1a;登录萤石云->控制台->我的资源->设备列表->列表中&#xff1a;查看通道->监控地址 appKey和appSecret获取&#xff1a;登录萤石云->控制台->我的账号->应用信息->右侧&#xff1a;应用密钥 下载ezuikit…

外卖项目(项目优化3)12---前后端分离开发

目录 问题描述&#xff1a;184 一、前后端分离开发 185 1.1介绍 185 1.2开发流程 1.3前端技术栈 二、YAPI 186 2.1介绍 2.2使用方式 三、Swagger 187 3.1介绍 3.2使用方式&#xff08;步骤&#xff09; 3.3Swagger---常用注解 188 四、项目部署 189 4.1部署架构…

美团面试应届生第二问:Volatile有什么作用?

文章目录volatile有什么作用&#xff1f;可见性证明指令重排证明不能保证原子性证明Volatile与Synchronized的区别volatile有什么作用&#xff1f; 保证线程的可见性禁止指令重排但是不能保证原子性 可见性证明 有如下静态成员变量num&#xff0c;初始值为0&#xff1b;有两…

38、Java——汽车租赁系统(JDBC+MySQL+Apache DBUtils)

​ ✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;乐趣国学的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例…

Python 面向对象简介

什么是面向对象&#xff1f; 面向对象是一种编程思想&#xff0c;在开发过程中关注的不是解决问题的步骤和过程&#xff0c;而是参与解决问题的对象和它们具备的行为。 01 面向过程和面向对象的区别 1、面向过程 面向过程在开发过程中关注的是解决问题的步骤和过程&#xf…

只会 Python 不行,不会 Python 万万不行

当下的环境大家有目共睹&#xff0c;未来一段时间情况如何&#xff0c;想必不少人心里也清楚&#xff0c;技术人走到中年&#xff0c;难免会焦虑&#xff0c;职场上干得不爽&#xff0c;但是跳槽也不容易&#xff0c;加上不少企业裁员&#xff0c;换个满意的工作更是难上加难。…

Promise 的状态, promise 指定多个成功/失败回调函数,都会调用吗?

实例对象promise中的一个属性 PromiseState pending 变为 resolved/fullfilled pending 变为 rejected 注意 对象的状态不受外界影响 只有这两种&#xff0c;且一个 promise 对象只能改变一次 一旦状态改变&#xff0c;就不会再变&#xff0c;任何时候都可以得到这个结果 无论…

美团应届生面试第一问:Object o = new Object()占用多少字节?

文章目录工具查看内存分配Java内存模型访问对象方式GC为什么Survivor要分为两个区域&#xff08;S0和S1&#xff09;&#xff1f;Survivor 为什么不分更多块呢&#xff1f;对象的生命周期小知识工具查看内存分配 Object o new Object();占用多少字节&#xff0c;我们借助open…