react setState调用为什么会触发整个组件函数的重新运行

react setState调用为什么会触发整个组件函数的重新运行
例如下面的代码 

function App(){const [age,setAge]=useState(5);const clickHandler=()=>{setAge(5)}console.log("点击div时候,我也会被刷新")return (<div onClick={clickHandler}><div>)
}

 那调用setAge时候到底发生了什么呢?

setAge是从useState里面解构出来的,那我们把关注点赚到useState里面。

setAge执行会导致App函数重新执行,但是age还是保存之前的结果!!

这说明

useState很可能一个闭包函数,执行后返回了个数组[state,setSate];

useState带代码可能如此:

const map=[];
const index=0;
const useState=(initValue)=>{index++;const setState=()=>{}return [map[index],setState]
}

APP函数重新运行

然后setState的执行会触发执行它的函数的重新运行,这个怎么写呢?

caller

当当当~~~~~~~~

Function.prototype.caller出场!!!!!!

大家都用过this,那个对象的方法调用我们的函数,我们的this就指向那个对象

那函数也有个属性,它在那个方法内执行,caller就指向那个函数的内存地址!!

代码改成如此:

const map=[];
const index=0;
const useState=(initValue)=>{index++;const caller=useState.caller;const setState=()=>{//重新执行App函数caller()}return [map[index],setState]
}

上面代码里面的index每次调用的时候都会递增,那setState调用时候会触发App的调用那index不是还是会继续递增么?如果App里面有多个useState,那就有问题了

这样无法做到index和我们useState的调用顺序保持一致!!!

那我们在caller()前面让index=0;重新赋值为0,这样就可以了

const map=[];
const index=0;
const useState=(initValue)=>{index++;const caller=useState.caller;const setState=()=>{//重新执行App函数index=0;caller()}return [map[index],setState]
}

这里的index申明是否可以省略呢,其实也可以,但是这样就得手动给App函数添加index属性,Function是Object的实现,所以它也可以有自己的属性。

完整代码改成如下:

在线链接:JS Bin - Collaborative JavaScript Debugging

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><button id="btn">add</button><p>输出结果<span id="txt">-</span></p><script>//react 内部源码///演示为什么age变化适合,App函数里面的其他打印回会执行//  var index = 0;//不需要了var map = [];const stateFn = {};function useState(init) {let caller = useState.caller;useState.caller.index++;let index = useState.caller.index;map[index] = map.hasOwnProperty(index) ? map[index] : init;const setState = (val) => {if (typeof val === 'function') {let currV = map[index];map[index] = val(currV);}else {map[index] = val}//重置App 函数对象的index索引caller.index = 0;//重新执行App函数caller()return map[index];}// stateFn.setState = setState;return [init, setState]} //react 组件 function App() {console.log("!!!!!调用setAge会触发App函数重新执行!!!!!!")const [age, setAge] = useState(0);const [year, setYear] = useState(2022);const btn = document.getElementById("btn");const txt = document.getElementById("txt");txt.innerHTML = `age:${age} year:${year}`;btn.onclick = () => {let ageResult = setAge((val) => val + 1);let yearResult = setYear((val) => val + 1);txt.innerHTML = `age:${ageResult} year:${yearResult}`;}}//正常写代码是不需要这样写的,可能编译器可以给他添加上去App.index = 0;//export default App; App()</script>
</body></html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/603231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode:228. 汇总区间 | 区间】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

分析抖音直播弹幕评论和礼物的websocket数据流信息,通过proto协议解析消息内容思路

现在定位到一个解析的大概位置&#xff1a; e.decode function(e, t) {e instanceof o || (e o.create(e));for (var n, i, s void 0 t ? e.len : e.pos t, u new r.webcast.im.MemberMessage(r.webcast. 通过请求找到发送请求的js代码位置&#xff0c;然后通过跟踪这…

【远程计算机,这可能是由于 Credssp 加客数据库修正】解决方案

1、winR打开运行窗口 输入gpedit.msc命令&#xff0c;若找不到&#xff0c;可以进行如下文件编辑格式为cmd echo offpushd "%~dp0"dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txtdir /b C:\Win…

centos通过yum 安装nginx和基本操作

Yum安装Nginx 1、配置Centos 7 Nginx Yum源仓库(注意系统版本要匹配&#xff0c;此步根据环境来确认&#xff0c;不是必须的&#xff09; rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 2、安装Nginx yum install n…

宏基因组序列无参考基因组装工具idba-ud的介绍及详细使用方法

介绍 idba-ud工具是一种用于组装无参考基因组的工具&#xff0c;它可以将高通量测序数据转化为基因组序列。它是idba工具的升级版本&#xff0c;专门用于组装多样性的无参考基因组。 idba-ud的主要作用是通过组装测序数据&#xff0c;生成无参考基因组的序列。它能够处理短读…

C#中List<T>底层原理剖析

C#中List底层原理剖析 1. 基础用法2. List的Capacity与Count&#xff1a;3.List的底层原理3.1. 构造3.2 Add()接口3.3 Remove()接口3.4 Inster()接口3.5 Clear()接口3.6 Contains()接口3.7 ToArray()接口3.8 Find()接口3.8 Sort()接口 4. 总结5. 参考 1. 基础用法 list.Max() …

【tkinter 电子时钟 实现时间日期 可实现透明 无标题栏】

下面是一个使用tkinter实现的简单的电子时钟&#xff0c;包括时间和日期的显示。该窗口是透明的&#xff0c;没有标题栏。 效果&#xff1a; import tkinter as tk from datetime import datetimedef update_time():now datetime.now()time_label.configure(textnow.strftim…

CSS效果(工作中常用)

1、css文字溢出省略号 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略号显示 white-space: nowrap; // 规定段落中的文本不进行换行 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略…

labelme的json转mask,实测有效

1、创建一个conda的虚拟环境 conda creat -n labelme python3.82、转到你的标注文件夹&#xff08;包括json和图片&#xff09; cd C:/Users/Administrator/Desktop/json3、你需要在标注文件夹下用txt写下以下代码&#xff0c;并保存bat文件。 放在最后一个就可以了 echo of…

JSON和AJAX

AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一种无需重新加载整个页面就能更新部分网页的技术。它使用JavaScript的XMLHttpRequest对象来发送异步请求&#xff0c;并获取服务器响应。AJAX可以用于在不刷新页面的情况下更新网页内容、与服务器交换数据并更新…

while猜数字实例——C++版

案例描述&#xff1a;系统随机生成一个1到100之间的数字&#xff0c;玩家进行猜测&#xff0c;如果猜错&#xff0c;提示玩家数字过大或过小&#xff0c;如果猜对恭喜玩家胜利并退出游戏。 逻辑框图&#xff1a; #include<bits/stdc.h> using namespace std; int main()…

如何在GitHub正确提PR(Pull Requests),给喜欢的开源项目贡献代码

最好的中文TTS项目Bert-vits2更新了中文特化分支&#xff0c;但可能由于时间仓促&#xff0c;代码中存在不少的bug&#xff0c;作为普通用户&#xff0c;有的时候也想为自己喜欢的开源项目做一点点贡献&#xff0c;帮助作者修改一些简单的bug&#xff0c;那么该如何开始&#x…

Vert.x学习笔记-什么是事件总线

广义事件总线介绍Vert.x的事件总线Vert.x的事件总线的实现方式Vert.x的事件总线通信模式事件总线与消息队列的区别点对点通信模式请求-应答通信模式发布-订阅通信模式 Vert.x的事件总线应用场景Vert.x的事件总线消息Vert.x的事件总线消息示例Vert.x的事件总线的消息类型 拓展 广…

【Spark精讲】SparkSQL Join选择逻辑

SparkSQL Join选择逻辑 先看JoinSelection的注释 If it is an equi-join, we first look at the join hints w.r.t. the following order: 1. broadcast hint: pick broadcast hash join if the join type is supported. If both sides have the broadc…

四、C#高级特性(动态类型与Expando类)

在C#中&#xff0c;动态类型和ExpandoObject类是两个与运行时类型系统相关的特性&#xff0c;它们提供了更灵活的数据处理能力。 动态类型 动态类型是一种特殊的类型&#xff0c;允许你在运行时解析和操作对象的成员&#xff0c;而不需要在编译时知道这些成员的细节。使用动态…

通讯录排序(结构体)

输入n个朋友的信息&#xff0c;包括姓名、生日、电话号码&#xff0c;本题要求编写程序&#xff0c;按照年龄从大到小的顺序依次输出通讯录。题目保证所有人的生日均不相同。 输入格式: 输入第一行给出正整数n&#xff08;<10&#xff09;。随后n行&#xff0c;每行按照“…

【设计模式】解释器模式

一起学习设计模式 目录 前言 一、概述 二、结构 三、案例实现 四、优缺点 五、使用场景 总结 前言 【设计模式】——行为型模式。 一、概述 如上图&#xff0c;设计一个软件用来进行加减计算。我们第一想法就是使用工具类&#xff0c;提供对应的加法和减法的工具方法。 …

vue2中vuex详细使用

1.安装 说明&#xff1a;也就是版本号&#xff0c;一般vue2安装vuex3。 npm i vuex3.6.2 2.搭建架子 执行流程如下&#xff1a; 初始化状态&#xff1a;在state对象中定义了一个名为message的属性&#xff0c;并将其初始值设置为"启动"。 定义变更函数&#xff08…

Kafka(六)消费者

目录 Kafka消费者1 配置消费者bootstrap.serversgroup.idkey.deserializervalue.deserializergroup.instance.idfetch.min.bytes1fetch.max.wait.msfetch.max.bytes57671680 (55 mebibytes)max.poll.record500max.partition.fetch.bytessession.timeout.ms45000 (45 seconds)he…

前台收款单选择的保险公司 提示 往来户不属于该财务组织

前台收款单选择的保险公司 提示 往来户不属于该财务组织 问题避免 新增保险公司的时候&#xff0c;找一个已经存在的保险公司&#xff0c;利用多页签复制的方式来新增 保险公司 不然不能够自动生成 财务客户