react setState详解
React setState调用的原理
setState具体的执行过程如下:
- 首先调用setState()函数:
ReactComponent.prototype.setState = function(partialState, callback){// updater:一个带有形参的函数,返回被更新的状态对象。它可以接收到props和statethis.updater.enqueueSetState(this, partialState)if(callback){this.updater.enqueueCallback(this, callback, 'setState')}
}
enqueueSetState将新的state放进组件的状态队列里,并调用enqueueUpdate来处理将要更新的实例对象。
enqueueSetState: function (publicInstance, partialState) {// 根据 this 拿到对应的组件实例var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');// 这个 queue 对应的就是一个组件实例的 state 数组var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);queue.push(partialState);// enqueueUpdate 用来处理当前的组件实例enqueueUpdate(internalInstance);
}
setState()最终通过enqueueUpdate更新state。
function enqueueUpdate(component) {ensureInjected();// 注意这一句是问题的关键,isBatchingUpdates标识着当前是否处于批量创建/更新组件的阶段if (!batchingStrategy.isBatchingUpdates) {// 若当前没有处于批量创建/更新组件的阶段,则立即更新组件batchingStrategy.batchedUpdates(enqueueUpdate, component);return;}// 否则,先把组件塞入 dirtyComponents 队列里,让它“再等等”dirtyComponents.push(component);if (component._updateBatchNumber == null) {component._updateBatchNumber = updateBatchNumber + 1;}
}
在enqueueUpdate中通过batchingStrategy的isBatchingUpdates属性来判断当前是否处于批量创建/更新组件的阶段。
batchingStrategy对象可以理解为“锁管理器”。这里的“锁”是指isBatchingUpdates变量。isBatchingUpdates初始值为false,表示并未进行任何批量更新操作。每当React调用batchedUpdate去执行更新动作时,会先把这个锁给锁上(置isBatchingUpdates为true),表明“现在正处于批量更新过程中”。当上锁后,更新需要更新的组件都要在队列中等待下一次批量更新。
setState()将对组件state的更新排入队列,并通知React需要使用更新后的 state重新渲染此组件及其子组件。你需要将setState()视为请求而不是立即更新state(可能为异步的!!!)。因为React会将多次的setState()放在一起一并执行,这样可以提升效率,减少页面渲染次数。
因为setState()并不总是立即更新state,可能会推迟更新。这导致在调用setState()后立即读取this.state有可能会拿到未更新之前的state。为了解决这个问题,我们可以使用componentDidUpdate或setState(updater, callback)的回调函数,保证在state更新后再执行。
总结:setState()用于更新状态,它接受两个参数,第一个参数可以传入一个对象,也可以传入一个updater函数。传入的对象代表需要更新的状态及状态值。updater为一个带有形参的函数,返回被更新的状态对象,可以接收到state和props;第二个参数是一个可选的回调函数,在状态更新完后进行回调。setState()并不会立即执行状态的更新,而更像是更新状态请求。
- 在调用setState()后React会调用enqueueSetState()方法将需要更新的state入队。
- 接着调用enqueueUpdate方法里面的batchingStrategy.isBatchingUpdates属性判断当前是否处理批量更新的阶段。若处于,则将需要更新state的组件放入dirtyComponent队列中等待下一次批量更新;若不处于则立即更新组件。
setState调用之后发生了什么?是同步还是异步的?
在代码中调用setState后React会将传入的对象与当前组件的状态合并,然后触发调和过程。经过调和过程,React会根据新的状态构建React元素树,然后计算新老元素树节点的差异,根据差异对页面进行渲染。。
根据场景来决定是同步还是异步。
- 同步:在React无法控制的地方,比如原生事件,例如:addEventListener、setTimeout、setInterval等事件中,就只能同步更新。
- 异步:在React生命周期和合成事件中,React可以把多次setState合并到一起进行更新,提高效率。
setState设计为异步,可以提升性能。如果每次setState都要进行一次更新,那么意味着render函数会被频繁调用,这样效率很低。React采用延迟更新策略,可以把多次setState合并到一起进行更新,提高效率。
对于相同状态,同时调用setState,只有最后一个setState会生效,而不是单纯的累加。
// 每次点击按钮value的值+2,而不是+3
<button onClick={() => (setValue(value + 1), setValue(value + 2)}
>value + 1
</button>
getDefaultProps和defaultProps
getDefaultProps和defaultProps用于指定属性的默认值。
// ES5
getDefaultProps: function(){return {autoPlay: false,maxLoops: 10}
},// ES6
// 静态函数:使某个函数只在一个源文件中有效,不能被其他源文件所用
static defaultProps = {name: "lsw"
}
setState的第二个参数是什么?
setState的第二个参数是一个回调函数,在组件重新渲染完后执行,等价于在componentDidUpdate中执行。在这个回调函数中可以拿到更新的后state的值。
setState和replaceState的区别是什么?
setState用来设置状态,它接收两个参数,第一个参数是新的状态值,第二个参数是一个可选的回调函数,在状态改变后执行,可以获取到状态改变后的值。
React会将多次的setState合并为一次执行,提高性能,减少页面渲染次数。setState只是覆盖原来的状态,不会减少原来的状态。
replaceState只会保留nextState中的值,原来的state将被删除,相当于赋值。
state和props的区别
props是从组件外部传入的,主要用于父组件向子组件传递数据,具有只读性,只能通过外部组件主动传递数据来渲染子组件。state的作用是组件自己用来创建、修改、管理自身状态,他是组件的私有属性,不可通过外部修改,只能在组件内部通过this.setState修改,修改state会导致页面重新渲染。
react setState详解相关推荐
- React 源码系列 | React Context 详解
目前来看 Context 是一个非常强大但是很多时候不会直接使用的 api.大多数项目不会直接使用 createContext 然后向下面传递数据,而是采用第三方库(react-redux). 想想项 ...
- React.Children 详解
React.Children 详解 React.Children提供了处理 this.props.children 的 API,this.props.children 支持任何数据(组件.字符串.函数 ...
- RN和React路由详解及对比
前言 在平时H5或者RN开发时,我们业务场景中大部分都不是单页面的需求,那这时我们就能使用路由在进行多页面的切换.下面会对比一下react路由和RN路由的本质区别和使用方法. 路由(routing)是 ...
- rn php,RN和React路由详解及对比
前言 在平时H5或者RN开发时,我们业务场景中大部分都不是单页面的需求,那这时我们就能使用路由在进行多页面的切换.下面会对比一下react路由和RN路由的本质区别和使用方法. 路由(routing)是 ...
- 【React】 详解下一代开源混合应用框架Reapp
详解下一代开源混合应用框架Reapp reapp官网 转载于:https://www.cnblogs.com/dongdong230/p/4314978.html
- react中的setState详解
1.setState更新状态的2种写法 (1). setState(stateChange, [callback])------对象式的setState 1.stateChange为状态改变对象( ...
- React Hooks 详解
文章目录 为什么会有Hooks? 什么是Hooks? 一.userState():状态钩子 二.useEffect():副作用钩子 三.useContext():共享状态钩子 四.useReducer ...
- setState详解
我们都知道,React通过this.state来访问state,通过this.setState()方法来更新state.当this.setState()方法被调用的时候,React会重新调用rende ...
- react HOC详解
高阶组件HOC HOC是react项目中对组件逻辑复用部分进行抽离的一种解决方案,它是一种设计模式. 表现形式为 一个函数,该函数接受一个组件为参数,并返回一个新组件. Example---- imp ...
最新文章
- 微信小程序修改整体背景颜色
- Facebook最新研究:配合AR眼镜使用的腕带,可将神经信号转化为动作
- 3 行 Python 代码实现假聊天机器人(慎入:这是假机器人!!!)
- linux 软件集成工具箱,在PB中动态修改SQL语句
- Android activity生命周期
- 16.PAE分页实验
- 处理数字_6_NULL值的列的个数
- uWSGI 和 nginx 的区别?
- R 学习 - 图形设置中英字体
- display:inline的用法
- 1031 查验身份证 (15 分) 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。
- python怎么安装re模块_python模块模块re
- 小程序开发小游戏注意事项
- 摆动序列算法C语言,376 摆动序列 leetcode
- Miktex 安装遇到过的问题
- 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)
- linux字体怪异_Linux默认安装的字体模糊难看
- 2014522420145238 《信息安全系统设计基础》 第五次实验
- flex布局——flex布局
- 魔兽世界服务器存档位置,选择服务器也有大学问?新手入坑《魔兽世界》该在哪里“扎根”...