@H_403_1@原文地址:Functional setState is the future of React
原文作者:Justice Mba
译文出自:掘金翻译计划
原文链接:https://juejin.im/post/58cfcf6e44d9040068478fc6/
译者:reid3290
校对者:sunui,imink
React 首先会将你传递给 setState() 的参数对象合并到当前 state 对象中,然后会启动所谓的 reconciliation,即创建一个新的 React Element tree(UI 层面的对象表示),和之前的 tree 作比较,基于你传递给 setState() 的对象找出发生的变化,最后更新 DOM。 @H_403_1@但是,React 不会仅仅简单地 “set-state”。因为涉及到的工作量比较大,调用 setState() 并不一定会即时更新 state 》React 可能会将多次 setState() 调用批处理(batch)为一次 state 的更新。 @H_403_1@也就是说,React 并不会按照 setState() 的调用顺序即时更新 state,而是首先会将所有对象合并到一起,然后仅用该对象进行一次 “set-state”。 @H_403_1@如果用户高频多次的setState,React 则会对这些操作进行批处理:即将每次调用 setState() 时传递给它的所有对象合并为一个对象,然后用这个对象去做真正的 setState()。 @H_403_1@那么就意味着,下面这个函数执行的结果会是1,而不是我们希望的3。
原文作者:Justice Mba
译文出自:掘金翻译计划
原文链接:https://juejin.im/post/58cfcf6e44d9040068478fc6/
译者:reid3290
校对者:sunui,imink
温故知新
@H_403_1@1、React 是一个基于组件的 UI 库,组件基本上可以看作是一个接受某些属性然后返回 UI 元素的函数。 @H_403_1@2、React 提供了一个用于管理 state 的特殊函数 —— setState()。 @H_403_1@3、setState() 的作用机制:你传递给它一个对象,该对象含有 state 中你想要更新的部分。敲黑板,划重点
@H_403_1@setState() 不仅能接受一个对象,还能接受一个函数作为参数。该函数接受该组件前一刻的 state 以及当前的 props 作为参数,计算和返回下一刻的 state。this.setState(function (state,props) {
return {
score: state.score - 1
}
});
@H_403_1@好奇宝宝要问了,这么做的目的是什么?
@H_403_1@理由是,state 的更新可能是异步的。
@H_403_1@React 在更新 State 的时候发生了什么?》 React 首先会将你传递给 setState() 的参数对象合并到当前 state 对象中,然后会启动所谓的 reconciliation,即创建一个新的 React Element tree(UI 层面的对象表示),和之前的 tree 作比较,基于你传递给 setState() 的对象找出发生的变化,最后更新 DOM。 @H_403_1@但是,React 不会仅仅简单地 “set-state”。因为涉及到的工作量比较大,调用 setState() 并不一定会即时更新 state 》React 可能会将多次 setState() 调用批处理(batch)为一次 state 的更新。 @H_403_1@也就是说,React 并不会按照 setState() 的调用顺序即时更新 state,而是首先会将所有对象合并到一起,然后仅用该对象进行一次 “set-state”。 @H_403_1@如果用户高频多次的setState,React 则会对这些操作进行批处理:即将每次调用 setState() 时传递给它的所有对象合并为一个对象,然后用这个对象去做真正的 setState()。 @H_403_1@那么就意味着,下面这个函数执行的结果会是1,而不是我们希望的3。
...
state = {score : 0};
// 多次 setState() 调用
increasescoreBy3 () {
this.setState({score : this.state.score + 1});
this.setState({score : this.state.score + 1});
this.setState({score : this.state.score + 1});
}
...
@H_403_1@需要搞清楚的是,给 setState() 传递对象本身是没有问题的,问题出在当你想要基于之前的 state 计算出下一个 state 时还给 setState() 传递对象。这是不安全的!
@H_403_1@让函数式 setState 来完成这样的任务
@H_403_1@当你编写函数式 setState 的时候,更新操作会形成一个任务队列,稍后会按其调用顺序依次执行。
@H_403_1@核心概念是,使用函数式 setState,你可以传递一个函数作为其参数,当执行该函数时,React 会将更新后的 state 复制一份并传递给它,这便起到了更新 state 的作用。基于上述机制,函数式 setState 便可基于前一刻的 state 来更新当前 state。
更进一步
@H_403_1@函数式 setState 的强大之处 —— 在组件类外部声明 state 的更新逻辑,然后在组件类内部调用之:// 在组件类之外
function increasescore (state,props) {
return {score : state.score + 1}
}
class User{
...
// 在组件类之内
handleIncreasescore () {
this.setState(increasescore)
}
...
}
@H_403_1@这就叫做 declarative(宣告式編程)!组件类不用再关心 state 该如何更新,它只须声明它想要的更新类型即可。
@H_403_1@设想如下场景:你有一些很复杂的组件,每个组件的 state 都由很多小的部分组成,基于 action 的不同,你必须更新 state 的不同部分,每一个更新函数都有很多行代码,并且这些逻辑都存在于组件内部。不过有了函数式 setState,再也不用面对上述问题了!
@H_403_1@并且,基于函数式 setState,你就可以将 state 的更新逻辑抽离为一个模块,然后在组件中引入和使用该模块。让代码显得小而美。
import {increasescore} from "../stateChanges";
class User{
...
// 在组件类之内
handleIncreasescore () {
this.setState(increasescore)
}
...
}