React setState使用与深入理解

setState作用更改数据,重新渲染页面,直接进行更改数据,值会更新,但页面不会重新渲染

如不使用setState更改数据,则可以使用foceUpdate强制渲染页面

setState与foceUpdate区别:

相同点:

  • 都是重新渲染页面

不同点:

  • setState执行流程:先走shouldComponentUpdate=>ComponentWillUpdate
  • 使用setState后,如不使用shouldComponentUpdate则即使没有更改数据也会重新渲染组件
  • foceUpdate执行流程:直接走ComponentWillUpdate

setState知识点(重点):

  1. setState执行后,会调用shouldComponentUpdate在执行ComponentWillUpdate,在shouldComponentUpdate可以判断是否数据更改 从而来决定是否要重新渲染组件,如进行判断则每次setState都将会重新渲染组件(包括自组件)
  2. setState在执行时会把所有要更改的,合成一次后进行重新渲染  
  3. setState执行中如遇到相同内容更改,则会执行最后一个,前面相同的不执行
  4. setState属于异步情况下:在合成事件或者生命周期函数中都是异步操作
  5. 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}
			{num: 2}
        })
      //this.setState((state, props) => ({
  			//num: 2
	  //}));
        
       //this.setState(function(state, props) {
  			//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执行的顺序

  1. 先执行SetStateDemo2 ==> render  console.log('b')
  2. setState异步 所以先执行   console.log('a')
  3. componentDidMount  setState更改后再次执行 1
  4. 最后执行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同步异步问题

  1. setState在合成事件或者生命周期函数中都是异步操作
  2. setState在执行时会把其中所有要更改的,合成一次后进行重新渲染    
  3. 如果修改的状态都是一样的,则以最后一次为主
  4. 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)
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值