【React】类组件 state 状态用法

一、简单介绍

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

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

主要作用是用于组件保存、控制、修改自己的可变状态。state 在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改。你可以认为 state 是一个局部的、只能被组件自身控制的数据源。state 中状态可以通过 this.setState方法进行更新,setState 会导致组件的重新渲染。

  • props 和 state 都是js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)

二、基础用法

2.1、定义状态

切记:不要直接通过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;

2.2、修改状态

在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')
)
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
React组件是一种创建可重用UI组件的方式。它们是使用ES6类语法创建的,继承了React组件类。类组件可以包含状态(state)和生命周期方法(lifecycle methods),并且可以与其他组件进行交互。下面是一个简单的React组件的例子: ```jsx import React, { Component } from 'react'; class MyComponent extends Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('Component did mount'); } componentDidUpdate(prevProps, prevState) { console.log('Component did update'); } handleClick = () => { this.setState(prevState => ({ count: prevState.count + 1 })); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.handleClick}>Click me</button> </div> ); } } export default MyComponent; ``` 在上面的例子中,`MyComponent`是一个React组件。它包含一个状态`count`,一个生命周期方法`componentDidMount`,另一个生命周期方法`componentDidUpdate`,以及一个处理点击事件的方法`handleClick`。`render`方法返回了组件的UI。 当`MyComponent`被渲染时,它将显示当前的计数值和一个按钮。当按钮被点击时,`handleClick`方法将被调用,然后更新状态`count`的值。每次组件更新时,`componentDidUpdate`方法将被调用,可以在控制台中看到相应的输出。 需要注意的是,类组件需要继承`React.Component`类,并实现`render`方法来返回组件的UI。此外,构造函数用于初始化组件状态和属性,生命周期方法用于在组件的生命周期中执行特定的任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗不甘坠落的流星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值