React State状态

State

    • 状态(state)
    • 定义状态
    • 修改状态
    • 状态提升
    • 同步和异步

状态(state)

如果将 state 与 vue 中的某个点做类比的话,则其相当于 vue 组件中的 data ,作用就是用于存储当前组件中需要用到的数据。

状态就是组件描述某种显示情况的数据,由组件自己设置和更改,也就是说由组件自己维护,使用状态的目的就是为了在不同的状态下使组件的显示不同(自己管理)

定义状态

切记:不要直接通过this.state.xxx = xxxx形式去更改state的值。否则会包警告,警告如下:Do not mutate state directly. Use setState()。

  • 第一种设置方式
import React, {
      Component } from "react";

class App extends Component {
     
    // 构造函数初始state
    constructor(props) {
     
        super(props);// 作用 使子类可以获取到 父类中的this,子类没有自己的this
        this.state = {
     
            count: 0,
        };
    }
    render() {
     
        return <div>{
     this.state.count}</div>;
    }
}

export default App;
  • 第二种设置方式(推荐)
import React, {
      Component } from "react";

class App extends Component {
     
    // 常规初始化
    state = {
     
        count: 0,
    };
    render() {
     
        return <div>{
     this.state.count}</div>;
    }
}

export default App;

修改状态

在vue中,data 属性是利用 Object.defineProperty 处理过的,更改 data 的数据的时候会触发数据的 gettersetter,但是 React 中没有做这样的处理,如果直接更改的话,react 是无法得知的,所以,需要使用特殊的更改状态的方法 setState

  • 语法:this.setState(updater[,callback])
  • 第一个参数:
  • 负责对state自身进行修改(必须的),我们称之为updater
  • 第二个参数:
  • 是一个回调函数(可选),因为setState方法是异步的,如果想在更新好状态后做进一步处理,此时就可以用到第二个参数了。

  • updater参数传递的时候支持两种形式:

  • 对象形式函数形式

  • 对象形式

this.setState({
     
    count: this.state.count + 1
})
  • 函数形式
this.setState(state => {
     
    return {
     
        count: state.count + 1
    }
})

上述两种参数形式的updater建议使用函数形式。因为对象形式在批量使用的时候会存在问题,因此建议使用函数形式。

状态提升

如果有多个组件(兄弟节点)共享一个数据,把这个数据放到共同的父级组件中来管理 像vue中的bus

  • 主要用于组件间的传参
  • 需求:有一个文本框的组件,使用了两次以上,在一个文本框中输入内容的时候,另一个文本框会跟着发生变化

  • 第一种写法
import React, {
      Component } from "react";
import ReactDOM from "react-dom";
//Input 组件
//想要让两个文本框有关系,需要state在父组件中统一管理,这种方式叫做状态提升
class Input extends Component {
     
  constructor(props) {
     
    super(props);
    this.state = {
     
      content: ""
    }
  }
  //接收文本框的值
  changeValue = (ev) => {
     
    console.log(ev.target.value);
    //将接收的value值赋值给state
    this.setState({
     
      content: ev.target.value
    })
  }
  render() {
     
    return (
      <div>
        {
     /* 受控组件,受state控制的组件 */}
        <input type="text" value={
     this.state.content} onChange={
     this.changeValue} />
      </div>
    );
  }
}

class App extends Component {
     
  render() {
     
    return <div>
      第一个文本框:<Input /> <br />
      第二个文本框:<Input />
    </div>
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
  • 第二种写法
import React, {
      Component } from "react";
import ReactDOM from "react-dom";
//Input 组件
//想要让两个文本框有关系,需要state在父组件中统一管理,这种方式叫做状态提升
//因为state统一放在父组件中,将 state的值以参数的形式传给子组件,并且传递了父组件的函数到子组件
class Input extends Component {
     
  constructor(props) {
     
    super(props);
    this.state = {
     
      content: ""
    }
  }
  //接收文本框的值
  changeValue = (ev) => {
     
    //调用了父组件的函数
    this.props.onContentChange(ev.target.value)
  }
  render() {
     
    return (
      <div>
        {
     /* 受控组件,受state控制的组件 */}
        <input type="text" value={
     this.props.content} onChange={
     this.changeValue} />
      </div>
    );
  }
}
class App extends Component {
     
  constructor() {
     
    super();
    this.state = {
      content: "" }
  }
  handleContentChange = (newContent) => {
     
    this.setState({
     
      content: newContent
    })
  }
  render() {
     
    const {
      content } = this.state;
    return <div>
      第一个文本框:<Input content={
     content} onContentChange={
     this.handleContentChange} /> <br />
      第二个文本框:<Input content={
     content} onContentChange={
     this.handleContentChange} />
    </div>
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)

同步和异步

.setState是异步的,并不是本身的函数是异步的,setState函数本身是同步的,只不过,执行的顺序不同导致感受上是异步的。setState设置允许批量更新,看起来像是异步的。异步表现在合成事件和钩子函数上,会批量更新;在setTimeout,原生事件上表现出同步特性,也不会批量更新

  • this.setState()返回的对象或者函数,并不会覆盖之前的state里面的其它值,只是做了合并操作;
  • 对象形式在做相同操作的批量实现的时候,会出现只执行一个的情况,会导致业务错误;而函数形式不会存在这样的问题。
//1.引入 react
import React,{
     Component}from 'react'
//2.引入  react-dom
import ReactDOM from 'react-dom'
//可以改变的状态值记录到 state中
class App extends Component{
     
	//推荐使用 state设置初始值
	constructor(){
     
		super(); //作用 使子类可以获取到 父类中的this,子类没有自己的this
		this.state = {
     
			num:0
		}
	}
	componentDidMount() {
     
		//在钩子函数中执行 setState,也是异步操作
	}
    //这里需要使用箭头函数,避免this指向有问题,
    changeNum = () =>{
     
		// 我们想要实现+2的运算,你可能会这样写
		// 方式1:通过对象形式
		// this.setState({ num: this.state.num + 1 })
    	// this.setState({ num: this.state.num + 1 })
    	
		/* 
    		但是你这样更新两次,react中会认为是对对象的合并,
			合并的时候如果有一样的,后面的会替换掉前面的
    		Object.assign(
     		 prevState,
    		  {num:this.state.num+1},
    		  {num:this.state.num+1}
    		)
    	*/
    	
		// 虽然上面的方法行不通,但是我们可以通过下面的方法来实现+2
		// 方式2:通过函数形式,最终返回一个对象(像data)
		// prevState形参:原先的state对象(类似与vuex)
    	this.setState((prevState)=>{
     
			return {
     
				num:prevState.num+1
			}
		})
		this.setState((prevState)=>{
     
			return {
     
				num:prevState.num+1
			}
		})
	}
	//注意:jsx语法中不能写语句,只能写表达式。如三目运算符
	render(){
     
		//推荐写法,在使用 state中的值之前先解构
		const{
     num}= this.state
		return <div>
				点击数字加二{
     num}
				{
     /* onClick={this.changeNum} 事件的调用  */}
				<button onClick={
     this.changeNum}>++</button>
			</div>
	}
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
  • this.setState()setTimeout() 里面是表现出来的同步特性
//1.引入 react
import React,{
     Component}from 'react'
//2.引入  react-dom
import ReactDOM from 'react-dom'
//可以改变的状态值记录到 state中
class App extends Component{
     
	//推荐使用 state设置初始值
	constructor(){
     
		super(); //作用 使子类可以获取到 父类中的this,子类没有自己的this
		this.state = {
     
			num:0
		}
	}
    //这里需要使用箭头函数,避免this指向有问题,
    changeNum = () =>{
     
		//setState 在 setTimeout里面是表现出来同步特性
		setTimeout(() => {
     
			this.setState({
     num:this.state.num+1})
			this.setState({
     num:this.state.num+1})
		}, 1000);	
	}
	//注意:jsx语法中不能写语句,只能写表达式。如三目运算符
	render(){
     
		//推荐写法,在使用 state中的值之前先解构
		const{
     num}= this.state
		return <div>
				点击数字加二{
     num}
				{
     /* onClick={this.changeNum} 事件的调用  */}
				<button onClick={
     this.changeNum}>++</button>
			</div>
	}
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)

你可能感兴趣的:(React,全家桶,react,state,状态)