Эта статья изБлог Дэна.
Горячая точка сейчасhooks, поэтому Дэн решил написать статью оclass
Компоненты статьи 😂.
Проблемы, описанные в статье, не должны влиять на ваш кодинг, однако, если вы хотите глубже разобраться в том, как работает React, эта статья может оказаться полезной.
Первый вопрос:
Я даже не знаю, сколько раз я это писалsuper(props)
:
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = { isOn: true };
}
// ...
}
Конечно,предложение атрибута классаУпрощенный код:
class Checkbox extends React.Component {
state = { isOn: true };
// ...
}
В начале 2015 года версия React 0.13 ужестроить планыЭтот синтаксис поддерживается. Перед этим нам нужно продолжать писатьconstructor
, а затем позвонитеsuper(props)
.
Теперь давайте рассмотрим предыдущее письмо:
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = { isOn: true };
}
// ...
}
почему мы звонимsuper
? Можешь не звонить? Если он не передается при вызовеprops
Шерстяная ткань? Можно ли передать другие параметры?Прокрутите вниз с этими вопросами.
В JavaScript,super
Ссылка на конструктор родительского класса. (В React ссылка, естественно,React.Component
)
Следует отметить, что его нельзя использовать до тех пор, пока не будет вызван конструктор родительского класса.this
. На самом деле это не ограничение React, а ограничение JavaScript:
class Checkbox extends React.Component {
constructor(props) {
// 🔴 还不能用 `this`
super(props);
// ✅ 现在就能用啦
this.state = { isOn: true };
}
// ...
}
Пара JavaScriptthis
Есть причина для ограничений на использование. Предположим, что имеется следующее наследование:
class Person {
constructor(name) {
this.name = name;
}
}
class PolitePerson extends Person {
constructor(name) {
this.greetColleagues(); // 🔴 不能这么干,下面会讲原因
super(name);
}
greetColleagues() {
alert('Good morning folks!');
}
}
Если JavaScript позволяет вызыватьsuper
использовался раньшеthis
, через месяц нам нужно изменитьgreetColleagues
метод, атрибут name используется в методе:
greetColleagues() {
alert('Good morning folks!');
alert('My name is ' + this.name + ', nice to meet you!');
}
Но мы, возможно, забылиthis.greetColleagues();
звонитsuper
вызывали раньше, поэтомуthis.name
Задания пока нет. В таком коде трудно найти ошибки.
Чтобы избежать подобных ошибок,JavaScript заставляет разработчиков сначала вызывать конструкторsuper
, использоватьthis
.Это ограничение также распространяется на компоненты React:
constructor(props) {
super(props);
// ✅ 现在可以用 `this` 啦
this.state = { isOn: true };
}
Снова возникает вопрос: зачем проходить вprops
Шерстяная ткань?
Вы можете подумать, что вам нужно датьsuper
входящийprops
,иначеReact.Component
не могу инициализироватьthis.props
:
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
ru...недалеко от истины - на самом деле React делаетсделал так.
Однако, если вы случайно пропуститеprops
, звоните напрямуюsuper()
, вы все еще можетеrender
и другие способы доступаthis.props
(Можете попробовать, если не верите мне).
Почему это работает? потому чтоПосле вызова конструктора Reactprops
Назначить только что созданному объекту экземпляра:
// Inside React
const instance = new YourComponent(props);
instance.props = props;
props
Есть причина, почему это не работает.
Когда React добавляет поддержку классов, ему необходимо поддерживать не только классы ES6, но и другие реализации классов, такие как CoffeeScript, ES6, Fable, Scala.js, а также использование классов в TypeScript.непоследовательный. Итак, даже с классами ES6 вызовsuper()
React не накладывает слишком много ограничений по этому вопросу.
Но это означает, что когда вы используете React, вы можете использоватьsuper()
заменятьsuper(props)
Это?
Не делайте этого, потому что это принесет другие проблемы.Хотя React запустит конструктор дляthis.props
задание, но вsuper()
После вызова и до окончания конструктораthis.props
Все равно бесполезно.
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); // 😬 忘了传入 props
console.log(props); // ✅ {}
console.log(this.props); // 😬 undefined
}
// ...
}
Если метод доступа вызывается в конструктореprops
метод, то ошибку будет труднее обнаружить.Поэтому я настоятельно рекомендую всегда использоватьsuper(props)
, даже если это не требуется:
class Button extends React.Component {
constructor(props) {
super(props); // ✅ We passed props
console.log(props); // ✅ {}
console.log(this.props); // ✅ {}
}
// ...
}
Приведенный выше код гарантируетthis.props
Всегда иметь ценность.
Есть еще одна проблема, которая, возможно, долгое время преследовала разработчиков React. Вы должны были заметить, что когда вы используете Context API в классе (будь то предыдущийcontextTypes
все еще присутствуетcontextType
API),context
Оба используются в качестве второго параметра конструктора.
почему бы нам не написатьsuper(props, context)
? Конечно, мы могли бы сделать и так, но контекстный API используется относительно редко, поэтому он вызывает меньше ошибок.
благодарныйпредложение атрибута класса, такие баги почти вымерли.Пока конструктор не объявлен явно, все параметры передаются автоматически. Итак, вstate = {}
выражение, вы можете получить доступthis.props
так же какthis.context
.