я слышалаHooksстал новым фокусом. Тем не менее, я хочу представить интересную часть компонента объявления класса через этот блог. как насчет?
Следующее не улучшит ваши навыки React. Но когда вы углубитесь в то, как все работает, вы обнаружите радость, которую они приносят.
Сначала рассмотрим первый пример.
я написалsuper(props)
Количество раз намного больше, чем я думал:
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = { isOn: true };
}
// ...
}
Конечно,class fields proposal(предложение JS) заставляет нас пропустить этот процесс:
class Checkbox extends React.Component {
state = { isOn: true };
// ...
}
Это синтаксис класса, поддерживаемый в React 0.13 в 2015 году.planned. существуетclass fieldsПрежде чем появится эта более разумная альтернатива, утверждениеconstructor
и позвониsuper(props)
Он всегда использовался как временное решение.
Но перед этим вернемся к примеру только для ES2015:
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = { isOn: true };
}
// ...
}
зачем звонитьsuper
? мы можемНе делайтеназови это? Если мы должны вызвать его, вызовите его, не проходяprops
Что случится? Будут ли еще параметры? Приходите и найдите ответ вместе.
JavaScript,super
Является ссылкой на конструктор родительского класса. (В нашем случае это указывает наReact.Component
)
Очень важно, что вы не можете использовать его в конструкторе до вызова конструктора родительского классаthis
Да, JavaScript не позволяет вам сделать это:
class Checkbox extends React.Component {
constructor(props) {
// 🔴 Can’t use `this` yet
super(props);
// ✅ Now it’s okay though
this.state = { isOn: true };
}
// ...
}
Есть причина, по которой JavaScript заставляет конструктор суперкласса выполняться до того, как вы прикоснетесь к этому . Подумайте об иерархии классов:
class Person {
constructor(name) {
this.name = name;
}
}
class PolitePerson extends Person {
constructor(name) {
this.greetColleagues(); // 🔴 This is disallowed, read below why
super(name);
}
greetColleagues() {
alert('Good morning folks!');
}
}
предположим вsuper
разрешено звонить раньшеthis
. Через месяц мы можем бытьgreetColleagues
добавлен кname
Атрибуты:
greetColleagues() {
alert('Good morning folks!');
alert('My name is ' + this.name + ', nice to meet you!');
}
Однако мы забыли объявитьthis.name
изsuper
Перед вызовом метода он был вызванthis.greetColleagues()
. так чтоthis.name
сталundefined
положение дел! Как видите, в результате код становится непредсказуемым.
Чтобы избежать этой ловушки,Обязательный для JavaScript, если вы хотите использовать его в конструктореthis
,Сразудолженсначала позвониsuper
. Пусть родительский класс сделает это заранее! Это ограничение также распространяется на определение других компонентов React:
constructor(props) {
super(props);
// ✅ Okay to use `this` now
this.state = { isOn: true };
}
Есть еще вопрос, почемуprops
?
Вы можете подумать, почемуsuper
пройтиprops
, дляReact.Component
Инициализировать в конструктореthis.props
:
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
На самом деле, это почти та же причина, что иточная причина.
Но иногда, даже при звонкеsuper
вечныйprops
параметры, вы по-прежнему можете использоватьrender
и другие методыthis.props
. (Если не верите мне, попробуйте сами!)
Как это достигается? Причина в том, что после того, как ваш компонент будет создан, он назначитprops
атрибуты объектов-экземпляров.
// Inside React
const instance = new YourComponent(props);
instance.props = props;
Так что даже если вы забудетеprops
Датьsuper
, React по какой-то причине все равно установит их позже.
Когда React добавил поддержку классов, он не просто добавил поддержку ES6, цель состояла в том, чтобы поддерживать как можно более широкую абстракцию классов. В то время мы были ещене ясноТакие как ClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScript или другие решения, как успешно определять компоненты, поэтому React не заботится о том, нужно ли его вызыватьsuper()
Да - даже ES6.
Так что можно просто использоватьsuper()
заменитьsuper(props)
?
лучше не надо. Потому что с этим все еще есть проблемы. Правильно, React может датьthis.props
Назначение. ноthis.props
вызовsuper
и пока конструктор не закончитсяundefined
:
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); // 😬 We forgot to pass props
console.log(props); // ✅ {}
console.log(this.props); // 😬 undefined
}
// ...
}
Если это относится к некоторым методам в конструкторе, их будет сложно отлаживать.Это также почему я продолжаю рекомендовать добавлять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
или позже добавлено в React 16.6contextType
API,context
будет передан как второй параметр конструктора).
так почему бы нам неsuper(props, context)
заменить его? На самом деле можем, но контекст используется реже, поэтому ям встречается не так много.
Когда будет предложено поле класса, большинство ям исчезнет. Если конструктор не указан, все параметры будут переданы автоматически. Это позволяет такие вещи, какstate = {}
выражение, если необходимоthis.props
илиthis.context
То же самое будет применяться.
В Hooks нам даже не нужноsuper
илиthis
. Но это на другой день.
перевести оригиналWhy Do We Write super(props)?