react 三大属性分享

react三大属性: state(内部状态)、props(外部属性)、refs(表示组件内某个元素)

state:

  1. state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

一、注意:

  1. 组件中render方法中的this为组件实例对象

  2. 组件自定义的方法中this为undefined,如何解决?

a) 强制绑定this: 通过函数对象的bind()

b) 箭头函数

  1. 状态数据,不能直接修改或更新

二、setState的两种形式:

1、函数形式的setState

setState(updater, [callback])------函数式的setState
   1.updater为返回stateChange对象的函数。
   2.updater可以接收到state和props。
   3.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
   
test = () => {
  // 函数形式的setState,函数形式的setState能够接收到两个参数,一个是state,另一个是props
  this.setState(state => ({count: state.count + 1}))
}

2、对象形式的setState

setState(stateChange, [callback])------对象式的setState
   1.stateChange为状态改变对象(该对象可以体现出状态的更改)
   2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
     
test = () => {
  // 对象形式的setState
  const count = this.state.count + 1;
  this.setState({count})
}

总结:

1.对象式的setState是函数式的setState的简写方式(语法糖)

2.使用原则:

        (1).如果新状态不依赖于原状态 ===> 使用对象方式

        (2).如果新状态依赖于原状态 ===> 使用函数方式

        (3).如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取

三、使用过setState之后能否立即获取状态更新后的值(否),如何立即获取到?

test = () => {
  // 函数形式的setState,函数形式的setState能够接收到两个参数,一个是state,另一个是props
  this.setState(state => ({count: state.count + 1}))
  console.log('函数形式的setState更新后:', this.state.count)
}

image.png

如何立即获得?

test = () => {
  this.setState(state => ({count: state.count + 1}), () => {
    console.log('函数形式的setState更新后:', this.state.count)
  })
}

image.png

四、使用setState()来更新状态时是异步还是同步?(页面同步更新,但是直接console.log打印是未更新的)

判断setState()更新状态时异步还是同步的,主要是看执行setState的位置

  1. 在React控制的回调函数中(生命周期钩子,react事件监听回调)这种情况是异步的。

  2. 在非react控制的异步回调函数中(定时器回调/原生事件监听回调/promise回调)这种情况是同步的。

五、异步举例

  • 在React事件回调函数中使用setState(异步的)

// React事件回调函数中
update1 = () => {
    console.log('React事件回调函数更新之前:',this.state.count);
    this.setState(state => ({count: state.count + 1}))
    console.log('React事件回调函数更新之后:',this.state.count);
}

image.png

  • 在生命周期钩子函数中使用setState(异步的)

// 在生命周期钩子函数中
componentDidMount() {
    console.log('生命周期钩子函数更新之前:',this.state.count);
    this.setState(state => ({count: state.count + 1}))
    console.log('生命周期钩子函数更新之后:',this.state.count);
}

image.png

六、同步举例

  • setTimeout

// 定时器回调
update2 = () => {
    setTimeout(() => {
        console.log('setTimeout 更新之前:', this.state.count);
        this.setState(state => ({ count: state.count + 1 }))
        console.log('setTimeout 更新之后:', this.state.count);
    })
}

image.png

  • 原生onclick

update3 = () => {
    const h1 = this.refs.count;
    h1.onclick = () => {
        console.log('onclick 更新之前:', this.state.count);
        this.setState(state => ({ count: state.count + 1 }))
        console.log('onclick 更新之后:', this.state.count);
    }
}

image.png

  • Promise

update4 = () => {
    Promise.resolve().then(value => {
        console.log('Promise 更新之前:', this.state.count);
        this.setState(state => ({ count: state.count + 1 }))
        console.log('Promise 更新之后:', this.state.count);
    })
}

image.png

七、经典面试题

一道关于setState的经典面试题 - CodeSandbox

答案解析(按输出顺序进行解析):

第1个输出: react首先会渲染下组件,此时获取到的count值是state中存的初始值,所以是0.

第2、3输出:执行完render之后,会进入componentDidMount钩子函数,遇到两个对象式的setState会进行合并,但由于此时在钩子函数中,获取state是异步的,所以打印的都是0,但是当遇到函数式的setState,则不会合并,此时count的值已经变为了3.

第4输出:此时componentDidMount中出了Promise和setTimeout外都执行了,上面的代码对JS来说都属于同步代码,此时可以进行更新render了,所以打印了render 3.

第5输出:setTimeout和Promise中,由于Promise是微任务,所以优先执行,在执行的时候,这里的setState是同步更新state的,所以调用一次setState就要调用一次render,所以第五行打印的是render: 4.

第6输出:执行log操作,打印的是Promise: 4.

props:

  1. 每个组件对象都会有props(properties的简写)属性

  2. 组件标签的所有属性都保存在props中

作用:

  1. 通过标签属性从组件外向组件内传递变化的数据

  2. 注意: 组件内部不要修改props数据

编码操作:

// 1、内部读取某个属性值
this.props.name
​
// 2、对props中的属性值进行类型限制和必要性限制
Person.propTypes = {
  name: PropTypes.string.isRequired,
  age:PropTypes.number.
}
​
// 3、将对象的所有属性通过props传递
<Person {...person}/>
​
// 4、默认属性值
Person.defaultProps = {
  age: 18,
  sex: 'male'
}

Refs:

组件内的标签可以定义ref属性来标识自己

编码操作:

// 1、字符串形式的ref
<input ref="input1" />
// 通过this.refs.input1 获取值  
  // const {input1} = this.refs 
  // console.log(inout1.value)
  
// 2、回调形式的ref
<input ref={(c) => {this.inputValue = c}} />
// 通过this.inputValue 获取值 
   //const {inputValue} = this
   //console.log(inputValue.value)
​
// 3、createRef创建ref容器
myRef = React.createRef()
<input ref={this.myRef} />
// 通过this.myRef.current.value 获取值

参考:React中的setState更新state是同步还是异步的?_Always-Learning-CSDN博客

Guess you like

Origin blog.csdn.net/qq_39650208/article/details/120354540