65.9K
CodeProject 正在变化。 阅读更多。
Home

在 React 中初始化 State 的位置

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2018 年 5 月 28 日

CPOL

4分钟阅读

viewsIcon

6622

啊,初始化状态的各种方法。这可能令人困惑。是将 state = {...} 直接放在类里面,还是编写一个构造函数并在构造函数里面写 this.state = { ... }?并且,你是否需要完全使用构造函数?

啊,初始化状态的各种方法……这可能令人困惑。是将 state = {...} 直接放在类里面,还是编写一个构造函数并在构造函数里面写 this.state = { ... }?并且,你是否需要完全使用构造函数?

初始化状态的两种方法

在 React 组件中初始化状态有两种方法:在构造函数内部,以及直接在类内部。这里有一些例子。

在构造函数内部

在构造函数内部初始化状态如下所示

class App extends React.Component {
  constructor(props) {
    // Required step: always call the parent class' constructor
    super(props);

    // Set the state directly. Use props if necessary.
    this.state = {
      loggedIn: false,
      currentState: "not-panic"
      someDefaultThing: this.props.whatever
    }
  }

  render() {
    // whatever you like
  }
}

当组件类被创建时,构造函数是第一个被调用的方法,所以它是初始化所有东西的正确位置 - 包括状态。类实例已经在内存中创建,因此您可以使用 this 在其上设置属性。

这是唯一一个可以在等号左侧使用 this.state 的地方。在其他任何地方,都应该始终使用 this.setState 而不是使用 this.state.whatever = ... - 这样,React 就会知道您更改了某些内容,并且它可以重新渲染组件。

在编写构造函数时要注意的一件事是确保调用父类的构造函数:上面示例中的 super(props) 行。默认构造函数(由 JS 在你创建类时提供)会自动调用 super 并传入任何参数。

通过编写您自己的构造函数,您正在覆盖该默认行为,除非您自己调用 super,否则如果父类需要进行一些初始化,这可能会导致错误。

是否需要构造函数?

您不需要编写一个,因为 JS 提供了一个默认构造函数。要了解这是如何工作的,请尝试在浏览器的控制台中运行这 3 行

class Parent { constructor(arg) { console.log('constructing Parent with', arg) } }
class Child extends Parent {}
new Child(5);

请注意,当您创建一个新的 Child 时,它会打印“constructing Parent with 5”,即使 Child 没有明确定义的构造函数,并且没有明确地使用 super(arg) 调用父类的构造函数。 当您没有定义自己的构造函数时,JS 会自动处理这个 super 调用。

直接在类内部

初始化状态的第二种方法是直接在类定义内部,使用类属性。这看起来像这样

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

  render() {
    // whatever you like
  }
}

简洁明了!这里有几点需要注意

  • 没有构造函数
  • 直接引用 state 属性。它不是 this.state,只是 state
  • 范围在类内部,但不在方法内部。
  • 您仍然可以引用 this.props(和 this.context)。
  • 这是一个类 实例 属性,而不是静态属性,您可能将其用于 propTypes(例如 static propTypes = {...})。

在我写这篇文章时,类属性语法是一个 Stage 3 proposal,所以它还没有成为官方的 JS 规范的一部分。要使用它,您需要启用 Babel 的类属性转换

但是!如果您使用 Create React App 来引导您的项目,它已经启用了类属性转换,并且您今天就可以开始使用这个类属性语法了。

哪个更好?构造函数还是不使用?

和所有事情一样,这取决于您。

我更喜欢类属性的简洁外观。我不喜欢构造函数的额外样板,并且必须记住调用 super(props)(尽管 ESlint 可以提醒你这样做,而且 Create React App 的配置开箱即用)。

您可能已经看到在构造函数中绑定了事件处理函数,并且可能认为构造函数是必需的。我正在谈论这样的代码

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

  handleClick(event) {
    // do stuff
  }
}

类属性功能支持的另一种语法可以使这个构造函数不必要:您可以将属性设置为等于箭头函数,并且箭头函数继承类实例的 this 绑定,因此您不必显式地绑定它。它看起来像这样

class Thing extends React.Component {
  // This is all you need to do:
  handleClick = (event) => {
    // do stuff
  }
}

这起初看起来可能有点奇怪,但您可以这样想

// This statement:
const add = (a, b) => console.log(a + b);

// Can be thought of as assigning an arrow function to `add`:
const add = arrowFunction;

// where `arrowFunction` is expanded to:
(a, b) => console.log(a + b)

考虑到这一点,再看一下上面的 class Thing 示例。希望它看起来不那么奇怪。如果您仍然讨厌它,请花一些时间并编写更多箭头函数。我最初也有同样的问题。你的眼睛会适应的 :)

在 React 中初始化状态的位置最初由 Dave Ceddia 于 2018 年 3 月 29 日在 Dave Ceddia 上发布。

© . All rights reserved.