当前位置:首页>编程日记>正文

React学习手记5-细说组件state

设计state

state是跟UI相关的,组件的任何UI改变都可以从state的变化中反映出来。state代表一个组件UI呈现的最小状态,没有任何多余的状态,也不应该存在通过其他状态计算而来的中间状态。

1. 多余的中间状态
//totalCost  就是一个多余的状态,因为其可以通过list计算而来。
{list: [], //购物车列表totalCost: 0  //总价格
}2. 不跟UI相关的变量作为组件实例的普通属性
// 计时器例子
componentDidMount() {this.timer = setInterval(this.updateDate, 1000)
}
复制代码

state一般又分为两种类型:

1 用作渲染组件使用到的数据来源

2 用作组件UI展示的判断依据

this,state = {user: "Tom",  //展示内容数据isLogin: true  // 展示判断依据
}{ this.state.isLogin ? <h1>Hello, {this.state.user}</h1> : null }复制代码

修改state

状态可以通过this.state.xxx来直接获取,但是修改state缺需要多多注意:

1. 不能直接修改state

直接修改state,尽管不会报错,但是不会触发render,正确的方法是使用setState

this.setState({ title: "react"})

2. state的更新是异步的

调用setState并不会立刻改变state,而是把要修改的状态放入一个队列中,React会优化真正的执行时机。可能会将多次setState的状态修改合并到一次状态修改。所以不能依赖当前的state,计算下一个state。

比如,点击一个购买按钮,购买的数量就会加1。如果连续点击两次,则会连续两次调用this.setState({ quantity: this.state.qunatity + 1 })。  在合并为一次修改得情况下,相当于等价执行如下代码: 

Object.assign(previousState, {quantity: this.state.qunatity + 1 }, {quantity: this.state.qunatity + 1 })复制代码

最终购买的数量只增加1。

所以解决办法是,调用setState,传入一个函数作为参数。这个函数有两个参数,第一个是当前的最新状态的前一个状态preState,第二个参数是当前最新的属性props

this.setState((preState, props)=> ({counter: preState.quantity + 1
}) )复制代码

3. state的更新是一个合并的过程

当调用setState修改组件状态时,只需传入发生改变的state,而不是组件完整的state,因为组建的state的更新过程是一个合并的过程。

this,state = {user: "Tom",  //展示内容数据isLogin: true  // 展示判断依据
}
// 只需传入改变的state
this.setState({user: "Tony"
})复制代码

不可变对象

React官方建议把state当做不可变对象,一方面,直接修改this.state,组件并不会重新render;另一方面,state中包含的所有状态都应该是不可变对象。当state中的某个状态返生变化,应该重新创建这个状态对象,而不是直接修改原来的状态。如何创建,分三种情况:

1. 状态的类型是不可变类型(数字  字符串 布尔值 null undefined)

因为状态是不可变类型,所以直接给要修改得状态赋值一个新值即可

2. 状态的类型是数组

不能使用push、pop、shift、unshift、splice等方法修改数组类型的状态,因为这些方法都是在原数组的基础上修改,而concat、slice、filter会返回一个新的数组。也可以使用ES6的数组扩展语法

通常如果需要使用push、splice等方法,首先会先调用slice方法,返回一个新的组数,在新数组上使用push等方法。

this.setState(preState => ({books: preState.books.concat(["nodejs"]}
}))
复制代码

this.setState(preState => ({books: [...preState.books, "nodej"]
}))复制代码

3. 状态的类型是普通对象

// 使用ES6的Object.assgin 方法
this.setState(preState => ({people: Object.assign({}, preState.owner, {name: "Tom"})
}))复制代码

// 使用对象扩展方法
this.setState(preState => ({people: {...preState.owner, name: "Tom"}
}))复制代码

为什么React推荐组件的状态是不可变对象,原因大概有两点:

1. 防止原有对象意外修改。虽然react使用setState来改变state,但是直接this.state.xx = yy直接赋值并不会报错,只是不会触发render,但是state确实发生了变化,有可能导致不可预期的错误。

2. 处于性能考虑,可以在shouldComponentUpdate方法中仅仅比较两次状态对象的引用就可以判断状态是否发生了改变。 尤其我们在使用pureComponent组件时,其内部会在shouldComponentUpdate执行“浅比较”,就是只比较this.state.aa === nextState.aa,通过判断对象引用是否变化,如果对象变化但是引用没有变,及在原有对象修改(push、pop等方法),也不会触发render,这个要特别注意了。



http://www.coolblog.cn/news/41dcc2b4b3ba7c11.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐