React基础11 React中初始化state的两种方法

初始化state的两种方法

在React的组件中可以在两个位置来初始化state:(1)在组件的constructor中;(2)直接在class中利用属性赋值的方式

constructor

constructor中初始化state如下所示:

class App extends React.Component {
  constructor(props) {
    // 必须在这里通过super调用父类的constructor
    super(props);

    // 给state赋值,可以使用props
    this.state = {
      loggedIn: false,
      currentState: "not-panic",

      // 在使用props为state赋值时要格外仔细
      someInitialValue: this.props.initialValue
    }
  }

  render() {
    // whatever you like
  }
}

当一个class组件创建之后,constructor会首先被调用,所以在construcot中可以来初始化所有值,包括state。class实例在内存中已经被创建,所以可以使用this来为state赋值

要注意的是,在constructor中可以不使用this.setState来为state直接赋值,除此之外其他位置都不能这样做:

// 除了在constructor中,其他位置都不要这样做
this.state.a = 123

只有通过setState才能通知React,我们修改了数据,React需要重新渲染组件。

还有要注意的是,在constructor中不要忘记使用super(props)来调用父类的constructor。默认的constructor(当创建一个class时,如果我们没有显式的声明constructor,JS会默认提供一个)会自动调用super,将将所有的参数传入

使用prop来初始化state

大多数情况下都不要使用prop来为State的初始化赋值,因为这会让你的数据来源不唯一,这常常会导致Bug。数据源唯一是最佳实践。

当组件的prop发生改变,组件会重渲染,所以没有必要将prop复制为state来保证porp永远是最新的值。

// 不要这样做
class BadExample extends Component {
  state = {
    data: props.data
  }

  componentDidUpdate(oldProps) {
    // 复制了prop的值给state之后
    // 必须保证在props更新时,state的值也随之更新
    if(oldProps.data !== this.props.data) {
      // This triggers an unnecessary re-render
      this.setState({
        data: this.props.data
      });
    }
  }

  render() {
    return (
      <div>
        The data: {this.state.data}
      </div>
    )
  }
}

// 正确的做法:
class GoodExample extends Component {
  render() {
    return (
      <div>
        The data: {this.props.data}
      </div>
    )
  }  
}

constructor是必须的吗?

并一定必须显式的定义constructor,因为JS会提供默认的constructor。比如下面这个例子:

class Parent { 
  constructor(arg) { 
    console.log('constructing Parent with', arg)
  } 
}

class Child extends Parent {}

new Child(5);
// constructing Parent with 5

当创建Child的实例时,控制台会打印出constructing Parent with 5,虽然Child类并没有显式的定义constructor,也没有显式的通过super(props)调用父类。当我们没有定义自己的constructor时,JS会自动完成super的步骤。

直接在Class中定义

第二种初始化state的方法就是直接在Class的内部,使用Class的属性来定义:

class App extends React.Component {
  state = {
    loggedIn: false,
    currentState: "not-panic",
    someDefaultThing: this.props.whatever
  }

  render() {
    // whatever you like
  }
}

比如使用construcot更加得直接、简介。要注意的是:

  • 没有定义constructor
  • state属性是直接引用的,并不是通过this.state来引用的
  • state的作用域是在Class内部,并不是一个方法的内部
  • 仍然可以使用this.propsthis.context
  • state是class的实例属性,并不是静态属性,不需要添加static关键字(就像为static propTypes {...}

哪种更好

习惯使用哪种,就使用哪种。

class属性的方式看起来更加简单,不再需要额外的模板代码(constructor),也不需要提醒自己调用super(props)

有的时候需要在constructor中处理事件处理函数(为函数绑定this,就像:

class Thing extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    // do stuff
  }
}

可以通过Class属性的另外一种形式来替代上面的形式,可以让一个属性等于一个箭头函数,箭头函数获得了class实例的this,所以不再需要在constructor中显式的去绑定:

class Thing extends React.Component {
  handleClick = (event) => {
    // do stuff
  }
}

参考

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值