探索React(第五期):React-State

153 阅读3分钟

发现熬夜时间过的还挺快的,昨天去看医生,医生说我再熬两年就可以进棺材了。

什么是state

react的组件免不了需要和用户进行互动,而react就是将组件看成一个状态机(state machines),一开始会有个初始状态,随着用户的互动,状态会发生变化,从而触发重新渲染UI。
当然了,props和state是比较类似的,都用于描述组件的特性,但是区别在于,state是私有的,并且完全受控于当前组件。

如何定义和使用state

//class类组件
class CommonItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "hello world",
    };
  }

  render() {
    return <div>{this.state.text}</div>;
  }
}
//函数式组件
function CommonItem() {
  const [state, setState] = useState("hello world");
  return <div>{state}</div>;
}

我们可以看到对于类组件和函数组件的state定义都是相似的,一个是在构造函数里初始化,一个则是通过useState这样的hook初始化。
稍稍需要注意的就是类组件中的构造函数,一般来说有三种用途,第一是指定this->super(props),第二是用来设置初始化的状态->this.state={},第三是将函数方法绑定到实例上。所以当你需要设置默认状态值的时候你就需要写上构造函数啦。

如何修改state

在react中,当我们需要改变视图的时候不应该直接对state进行修改,这样并不会重新渲染组件,而应该使用setState()。

//class类组件
class CommonItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "hello world",
    };
  }

  render() {
    return (
      <div
        onClick={() =>
          this.setState({
            text: "hello react",
          })
        }
      >
        {this.state.text}
      </div>
    );
  }
}
//函数式组件
function CommonItem() {
  const [state, setState] = useState("hello world");
  return <div onClick={() => setState("hello react")}>{state}</div>;
}

state的更新是同步还是异步?

首先需要明确的是,虽然我们讨论的是setState的同步异步,但是并不是setTimeOut、promise那种异步,而是指setState之后state会不会立即更新的问题。

<div
onClick={() => {
  console.log("step1", this.state.text);
  this.setState(
    {
      text: "hello react",
    },
    () => {
      console.log("step 3", this.state.text);
    }
  );
  console.log("step 2", this.state.text);
}}
>
{this.state.text}
</div>

上述代码的执行结果是按照step1--hello world,step2--hello world,step3--hello react的顺序,由此我们可以看出在setState之后并没有立即改变state的值,当前如果我们希望拿到setState更新后的值可以使用step3的方式使用一个回调函数即可。
这里还需要注意一个问题,在react以前的版本,是可以在一些特殊情况下setState是可以同步执行的,比如将setState写在setTimeOut里,这是因为源码中设置了一个executionContext的判断条件来判断setState是批量执行还是非批量执行,但是在react18之后,就不存在这个问题了,因为所有的setState都是异步批量执行了~~

修改state的注意事项

我们在修改state的时候,应当注意状态都应该是不可变对象,当state变化的时候,我们应该重新创建这个状态对象,而不是直接去修改原来的状态。当然对于不同的状态类型,也会有一定的差异。

值类型:数字、字符串、布尔值、nullundefined
this.setState({
    count:99,
    text:'hello world'
})
数组类型
const newList = this.state.list.concat('newList')
this.setState({
    list:newList
})
或者
const newList = [...this.state.list,'newList']
this.setState({
    list:newList
})
对象
const newItem = Object.assign({},this.state.item,{text:'hello world'})
this.setState({
    item:newItem
})
或者
const newItem = {...this.state.item,text:'hello world'}
 this.setState({
    item:newItem
})

关于状态提升

简单来说,就是当两个子组件需要利用到对方的状态的时候就需要用到状态提升。具体的做法就是将两个子组件的状态保存在它们共同的父组件中,通过props传递给子组件,而不是子组件自己维护一份state,这也是react中兄弟组件的一种简单通信方式。