React教程第四节 组件的三大属性之state
前言
状态 state
适用于类式组件中,而再函数式组件中需要使用 useState HOOK
模拟状态;
React的组件就是一个状态机
,通过与用户的交互,实现不同的状态,根据不同的状态展现出不一样的UI视图
并不是组件中所有的属性 都是组件的状态:
如:以下几种都不是组件的状态
1、自定义的常量(整个生命周期过程中没有变化),没有根据值的变化而进行视图渲染的属性
;
2、通过 props 传递得到的属性
;
3、没有在 render() 中使用到的属性
;
1、写法:
a、类式组件的写法
通过 ES6
类和React 的Component
类派生出来的类组件;
可以通过 state 管理组件内部的状态
,
通过继承 获取到 React Component类的生命周期
;
import React, { Component } from 'react'
// 首先是 类式组件
class MyState extends Component {
// constructor() {
// super();
// this.state = {
// count: 0
// }
// }
// 如果没有继承使用父组件的 this 则没有必要写 constructor
// 或者 声明状态属性
state = {
count: 0
}
handleIncrement = () => {
// 更新修改状态属性
this.setState({
count: this.state.count + 1
})
}
render(){
return(
<>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleIncrement}>+</button>
</>
)
}
}
export default MyState
b、函数式组件中的写法
import { useState } from 'react'
export default function MyState() {
// 通过 useState 声明一个 count 属性,以及修改 count的方法 setCount
const [count, setCount] = useState(0)
// 通过自定义事件 触发 count 累加
const handleIncrement = () => {
setCount(count + 1)
}
return (
<>
<h2>计数器:{count}</h2>
<button onClick={handleIncrement}>+</button>
</>
)
}
相比较类式组件,函数式组件书写更简洁更轻量;
函数式组件不能通过 State 管理函数中的状态
,如需要管理 需使用 useState Hook
进行处理;
函数式组件中没有生命周期
,只能通过 useEffect useCallback 模拟生命周期
函数式组件可以通过 props 接收参数状态
,并更新视图;
2、修改state
a、基本类型
number、string、null、undefined、boolean
主要以 16.8版本之后的写法
const [name, setName] = useState('Andy')
//修改名称
setState('Jack')
b、引用类型修改时候注意事项
对象、数组为引用类型,在React 的Diffing
算法中对比新旧引用类型时
,对比的是引用
,而不是引用的对象
,若引用的地址不变则不会触发视图更新,故需要返回新的对象或者数组
对象修改
注意:直接修改 这样是不会触发视图更新的
student.age = student.age + 1
如下修改才可以更新视图:
const [student, setStudent] = useState({
age: 18,
sex: '男'
})
// 通过扩展运算符
setStudent({...student, age: student.age + 1})
// 通过回调函数创建新对象
setStudent((pre) => {
console.log('==pre==', pre)
return{
...pre,
age: pre.age + 1
}
})
// 通过ES6 的 Object.assign() 方法修改
setStudent(Object.assign({}, student, {age:student.age + 1}))
数组修改
const [cars, setCars] = useState([
{name: '大众', price: 100},
{name:'奥迪', price:40}
])
// 添加数据
setCars([...cars, {name:'奥迪', price:90}])
const newCars = cars.concat([{name:'奥迪', price:90}])
setCars(newCars)
// 删除数据
setCars(cars.slice(1))
// 过滤
setCars(cars.filter(itm => itm.name === '大众'))
在React中对数组
进行修改,需要使用能返回新数组
的方法,因为如果数组的指针不改变,是不会触发视图更新的;
比如: 不要使用push、pop、shift、unshift、splice
等方法修改数组类型的状态,因为这些方法都是在原数组的基础上修改
3、state更新
异步更新
比如:
const [count, setCount] = useState()
const handleIncrement = () => {
setCount(count + 1)
// 这里log 输出的不是最新的 count;
console.log('===count=', count)
// 若想拿到最新的 count 需要如下:
const curCount = count + 1
setCount(curCount)
console.log('===curCount=', curCount)
}
比如:
const [count, setCount] = useState()
const handleIncrement = () => {
// 这些视图不会一次增加3、依然是1
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
console.log('===count=', count)
// 若要一次增加三
setCount((count) => count + 1)
setCount((count) => count + 1)
setCount((count) => count + 1)
// 或者
setCount((count) => count + 3)
}
因为:当我们传入多个 setState
的多个 Object 会被 shallow Merge
,而传入多个 setState 的多个 function
会被 “queue”
起来,queue 里的 function 接收到的 state(上面是 参数 )都是前一个 function 操作过的 state
。
合并更新
调用 setState
时,组件的 state 并不会立即改变
, setState
只是把要修改
的 state 放入一个队列
, React 会优化真正的执行时机,并出于性能原因,会将 React 事件处理程序中的多次React 事件处理程序中的多次 setState 的状态修改合并成一次状态修改。 最终更新只产生一次
组件及其子组件的重新渲染,这对于大型应用程序中的性能提升至关重要。
setCount(count + 1) // 加入队列 count + 1 任务
setCount(count + 1) // 加入队列 count + 1 count + 1 任务
setCount(count + 1) // 加入队列 count + 1 count + 1 count + 1 任务
// 合并为 count + 1 任务执行
原文地址:https://blog.csdn.net/weixin_39593730/article/details/143896968
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!