setState作用更改数据,重新渲染页面,直接进行更改数据,值会更新,但页面不会重新渲染
如不使用setState更改数据,则可以使用foceUpdate强制渲染页面
setState与foceUpdate区别:
相同点:
不同点:
- setState执行流程:先走shouldComponentUpdate=>ComponentWillUpdate
- 使用setState后,如不使用shouldComponentUpdate则即使没有更改数据也会重新渲染组件
- foceUpdate执行流程:直接走ComponentWillUpdate
setState知识点(重点):
- setState执行后,会调用shouldComponentUpdate在执行ComponentWillUpdate,在shouldComponentUpdate可以判断是否数据更改 从而来决定是否要重新渲染组件,如进行判断则每次setState都将会重新渲染组件(包括自组件)
- setState在执行时会把所有要更改的,合成一次后进行重新渲染 ?
- setState执行中如遇到相同内容更改,则会执行最后一个,前面相同的不执行
- setState属于异步情况下:在合成事件或者生命周期函数中都是异步操作
- setState属于同步情况下:在一个异步事件中执行(例如定时器)则setState将会是同步执行
直接更改,将不会重新渲染页面,例子如下:
import React from 'react'
export default class ChangeVal extends React.Component {
constructor(props) {
super(props)
this.state = {
title: '更改数据'
}
}
render() {
return (
<div>{this.state.title}</div>
)
}
componentDidMount() {
this.state.title = '更改了数据'
console.log(this.state.title) //更改了数据 但是视图没有更新
}
}
foceUpdate强制更新页面?
import React from 'react'
export default class ChangeVal extends React.Component {
constructor(props) {
super(props)
this.state = {
title: '更改数据'
}
}
render() {
return (
<div>{this.state.title}</div>
)
}
componentDidMount() {
this.state.title = '更改了数据'
console.log(this.state.title) //更改了数据 但是视图没有更新
this.forceUpdate() //不使用this.setState强制更新
}
}
使用setState更改(推荐)
import React from 'react'
export default class ChangeVal extends React.Component {
constructor(props) {
super(props)
this.state = {
title: '更改数据'
}
}
render() {
return (
<div>{this.state.title}</div>
)
}
componentDidMount() {
this.setState({
title:'更改了数据'
})
}
}
setState更改 (函数式更改)
import React from 'react'
export default class ChangeVal extends React.Component {
constructor(props) {
super(props)
this.setState((val) => {
console.log(val)//{num:0}
return {num: 2}
})
}
render() {
return (
<div>{this.state.title}</div>
)
}
componentDidMount() {
this.setState({
title:'更改了数据'
})
}
}
当点击按钮父组件只要执行了setState即使没有更改任何值,但父组件和子组件还是重新渲染
import React from 'react'
export default class SetStateDemo extends React.Component {
state = {
num: 0
};
handle = () => {
let { num } = this.state
this.setState({
})
}
render() {
console.log('是否更新')
let { num } = this.state
return (
<button onClick={this.handle} ><Small num={num} />按钮</button>
)
}
}
class Small extends React.Component {
render() {
console.log('子组件是否重新更新')
return (
<div ></div >
)
}
}
解决 this.setState不需要重新渲染 setState没有更改值则父组件和子组件都不会重新渲染 ? ?shouldComponentUpdate
import React from 'react'
export default class SetStateDemo extends React.Component {
state = {
num: 0
};
handle = () => {
let { num } = this.state
this.setState({
})
}
render() {
console.log('是否更新')
let { num } = this.state
return (
<button onClick={this.handle} ><Small num={num} />使用SetState更改组件问题</button>
)
}
//不进行重新渲染
shouldComponentUpdate(nextProps, nextState) {
if (nextState.num === this.state.num) { return false } return true
}
}
class Small extends React.Component {
render() {
console.log('子组件是否重新更新')
return (
<div ></div >
)
}
}
setState执行的顺序
- 先执行SetStateDemo2?==>?render??console.log('b')
- setState异步?所以先执行???console.log('a')
- componentDidMount??setState更改后再次执行?1
- 最后执行setState回调函数的??console.log(2)
import React from 'react'
export default class SetStateDemo2 extends React.Component {
constructor(props) {
super(props)
this.state = {
title: 'setState异步问题'
}
}
render() {
console.log('b') //第一个执行
return (
<div>{this.state.title}</div>
)
}
componentDidMount() {
this.setState({
title: '更改了数据'
}, () => {
console.log(2) //最后执行
})
console.log('a')//第二个执行
}
}
setState同步异步问题
- setState在合成事件或者生命周期函数中都是异步操作
- setState在执行时会把其中所有要更改的,合成一次后进行重新渲染 ? ?
- 如果修改的状态都是一样的,则以最后一次为主
- setState在一个异步事件中执行(例如定时器)则setState将会是同步执行
import React from 'react'
export default class ChangeVal2 extends React.Component {
constructor(props) {
super(props)
this.state = {
number: 0,
number2: 0
}
}
render() {
return (
<div >{this.state.number}{this.state.number2}
<button onClick={this.funchange}>更改</button>
</div>
)
}
funchange = ev => {
/*
setState中执行多次一样的 但是只会执行一次,因为它会一样的合并并且执行最后一次
*/
this.setState({
number: this.state.number + 1,
number2: this.state.number2 + 1,
number2: this.state.number2 + 1
})
/*
对应第一条异步:点击后页面+1了数据 但是打印还是+1之前的数据。
例如数据默认值是0 点击增加后页面显示1 但这里打印实际还是0 表明了setState是异步的
*/
console.log(this.state.number)
}
/*
把setState 放到一个异步操作中,就没有必要异步了,就变成了同步
*/
componentDidMount() {
setTimeout(() => {
this.setState({
number: this.state.number + 1,
number2: this.state.number2 + 1,
number2: this.state.number2 + 1 //对应第三条 修改状态一样,则以最后一次为主
})
console.log(this.state)
//默认是0 加1后页面显示1 这里也显示1 则表明当前setState是同步的
}, 1000)
}
}
?
|