简体   繁体   English

React ES6类中的实例属性

[英]Instance property in React ES6 class

How come in React you can define state like below: 如何在React中定义如下状态:

class Test extends React.Component {
  state = { foo: 'bar' }
}

But in order to define other instance properties you need to do it in the constructor or other functions? 但是,要定义其他实例属性,您需要在构造函数或其他函数中执行此操作吗? As in, you can't do this: 在这种情况下,您不能执行以下操作:

 class Test extends React.Component {
  myField = 0;

  render() {
    myField++
  }
}

You can do this: 你可以这样做:

class Test extends React.Component {
  myField = 0;

  render() {
    this.myField++ // use this to access class properties
  }
}

But avoid using normal class properties and use state properties like in your first example. 但是,避免像第一个示例那样使用普通的类属性并使用状态属性。 So, that you can: 因此,您可以:

  1. Re-render component when necessary using this.setState() . 必要时使用this.setState()重新渲染组件。
  2. Force update and re-render the component using this.forceUpdate() . 使用this.forceUpdate()强制更新并重新呈现组件。
  3. Re-render the parent component. 重新渲染父组件。
  4. Change properties from React's lifecycle hook for eg shouldComponentUpdate() 从React的生命周期挂钩更改属性,例如shouldComponentUpdate()

  5. Not allow to mutate the property from outside the scope for eg. 不允许从范围之外对属性进行突变,例如。 if you are using normal properties, then you can change it from the browser console. 如果您使用的是常规属性,则可以从浏览器控制台进行更改。


You might need normal properties like in scenario of: 您可能需要正常的属性,例如以下情况:

Set timer as normal class properties in the constructor 将计时器设置为构造函数中的常规类属性

this.timer = setTimeout(..)

Clear timer in componentWillUnmount 清除componentWillUnmount中的计时器

componentWillUnmount (clearTimeout(this.timer))

The answer is you can, but instead of myField++ , change it to this.myField++ . 答案是可以的,但是可以将其更改为this.myField++而不是myField++ this.myField++ An example created on snack @ here 一个在小吃@ 这里创建的示例

It really has nothing much to do with React but more on general class concept in JS. 实际上,它与React并没有多大关系,而更多涉及JS中的通用类概念。 Find out more about class 了解有关课程的更多信息

You can do this.myField++ . 您可以执行this.myField++ Though syntax is wrong since you must return something from render like: 虽然语法是错误的,因为您必须从render返回一些内容,例如:

class Test extends React.Component {
  myField = 0;

  render() {
    return <div>this.myField++</div>
  }
}

You won't see 1 there because React first sees myField's value and render it. 您不会在那里看到1 ,因为React首先看到myField的值并将其呈现。

But I think the actual question is not about how we use it. 但是我认为实际问题不在于我们如何使用它。 It is about a new proposal for ES: class-fields. 这是关于ES的新建议:类字段。 Here is an explanation for that: https://stackoverflow.com/a/50789811/7060441 这是对此的解释: https : //stackoverflow.com/a/50789811/7060441

This is a new proposal (class fields) for ES which is in [stage 3][1] right now. 这是ES的新提案(类字段),目前处于[阶段3] [1]。 To run a code written in this way you need a transpiler like Babel and an appropriate plugin. 要运行以这种方式编写的代码,您需要像Babel这样的编译器和相应的插件。

Before transpile: 转换前:

 class A { static color = "red"; counter = 0; handleClick = () => { this.counter++; } } 

After transpile (with stage 2 on Babel Repl): 转运后(Babel Repl的阶段2):

 class A { constructor() { this.counter = 0; this.handleClick = () => { this.counter++; }; } } A.color = "red"; 

In addition to the official proposal [2ality blog post][2] is a good source to see what are the details. 除了官方建议之外,[2ality博客文章] [2]是查看详细信息的好资源。

Here is a [reddit post][3] if you have time to read the discussion storm what is the reason behind this proposal :) 如果您有时间阅读讨论风暴,那么这是一个[reddit帖子] [3],该提案背后的原因是什么:)

The arrow function here is a different story. 这里的箭头功能是另外一个故事。 You can use instance properties without constructor and mix your code with standard functions. 您可以使用没有构造函数的实例属性,并将代码与标准函数混合。 But when you want to use something like that this won't work: 但是,当你想使用类似的东西, this是行不通的:

 class App extends React.Component { state = { bar: "baz"} foo() { console.log(this.state.bar) }; render() { return <div><button onClick={this.foo}>Click</button></div>; } } 

We need to bind our function in somehow like: 我们需要以某种方式绑定我们的功能:

 return <div><button onClick={this.foo.bind(this)}>Click</button></div> 

But, binding our function in a JSX prop is no so good since it will create our function in each render. 但是,将函数绑定到JSX prop中并不是很好,因为它将在每个渲染器中创建函数。

One way to do this nicely bind in our constructor: 一种很好地绑定到我们的构造函数中的方法:

 constructor(props) { super(props); this.foo = this.foo.bind( this ); } 

But, if I have to write a constructor what is the point? 但是,如果我必须写一个构造函数,那有什么意义呢? This is why you see arrow functions everywhere where we define the classes like your second example. 这就是为什么在我们定义类的地方到处都可以看到箭头功能的原因,就像您的第二个示例一样。 No need to bind to function thanks to arrow functions. 借助箭头功能,无需绑定功能。 But it is not directly related to this new proposal I think. 但是,我认为这与这项新建议没有直接关系。

[1]: https://github.com/tc39/proposal-class-fields [2]: http://2ality.com/2017/07/class-fields.html [3]: https://www.reddit.com/r/javascript/comments/6q0rov/es_proposal_class_fields/ [1]: https//github.com/tc39/proposal-class-fields [2]: http//2ality.com/2017/07/class-fields.html [3]: https:// www。 reddit.com/r/javascript/comments/6q0rov/es_proposal_class_fields/

That syntax is syntactic sugar. 该语法是语法糖。 Nothing "new" about JavaScript in this regard. 在这方面,关于JavaScript并没有什么“新鲜”的东西。 It abstracts out the concept of creating a constructor function for the sole purpose of declaring variables within the class 's context and does it for you. 它抽象出了创建构造函数的概念,其唯一目的是在class的上下文中声明变量并为您完成。 These are equivalent: 这些是等效的:

class Sample {
  dog = 1
}

class Sample {
  constructor() {
    this.dog = 1
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM