如果将
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 的数据的时候会触发数据的getter
和setter
,但是 React 中没有做这样的处理,如果直接更改的话,react 是无法得知的,所以,需要使用特殊的更改状态的方法setState
。
this.setState(updater[,callback])
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')
)