なぜsuper(props) を書くの? - React界のカリスマ「Dan Abramov」のブログ
なぜsuper(props) を書くの? - React界のカリスマ「Dan Abramov」のブログ:
以下はWhy Do We Write super(props)? の日本語訳です。
(翻訳、おかしい部分があるかもしれませんが自己責任でお願いいたします。)
これらの潜在的問題はReactを効率的に使うためには重要じゃない。でも、もしどうやって動いているか深く掘り下げることが好きなら面白いかもね
これが最初のやつ。
私は人生で
もちろん、
2015年に
でも、ES2015の機能のみを使って例に戻りましょう。
なぜ私たちはsuperを呼ぶの?呼ばなくてもいいの?もし呼ばないといけないなら、
JavaScriptではsuperは親クラスのコンストラクタを参照します。(この例では、親クラスはReact.Component実装を指しています。)
重要なのは、JavaScriptはあなたがコンストラクターで親のコンストラクターを呼ぶまで
あなたがthisを使う前にJavascriptが親のコンスラクターの実行を強制させるのには理由があります。クラス階層を考えてみてください
一ヶ月後、
しかし
ご覧のとおり、このようなコードは考えるのが非常に難しいのです。
この落とし穴を避けるために Javascriptはコンストラクターでthisを使いたい場合に
そして、この制限はクラス定義されたReactのコンポーネントにも適用されます。
他の疑問が残っています。なぜpropsを引数に渡すの?
真実からそれほど遠くないですよ。確かにやっています
しかし、どういうわけか引数(
どうやって動いているんだ?
Reactも
そう。だからもし
Reactがclassをサポートしたとき、ES6のクラスだけをサポートしたのではありません。
ゴールはより広いクラスの抽象概念をサポートすることでした。
コンポーネントを定義するのにClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScriptや他の方法がどれほど成功するのかは不明確でした。
だからES6のclassで
これは
多分そうじゃない。まだ紛らわしい。
確かに、Reactはコンストラクターが実行されたあとに
でも、親とあなたのコンストラクターの実行が終わるまでの間、
コンストラクタから呼び出されるメソッドでこれが発生した場合、デバッグするのはさらに困難になります。
厳密に必要というわけではないですが、私は常に
これはコンストラクタが終了する前でも
長年のReactユーザーは興味があるかもしれないことを最後に少々。
Context APIをclass(古いタイプのcontextTypesもしくはReact 16.6で追加された新しいcontextTypeのどちらでも)内で使用する時、
では、
明示的なコンストラクタがないと全ての引数は自動的に渡されます。
これはこのような式(
Hooksでは
しかし、これは別の日の話題としましょう。
なぜ私たちは super(props)
を書くの?
以下はWhy Do We Write super(props)? の日本語訳です。(翻訳、おかしい部分があるかもしれませんが自己責任でお願いいたします。)
Hooks
が最新でアツいって聞いたよ。皮肉なことだけどクラスコンポーネントの楽しい事実について述べてブログをスタートしたい。どうだ!これらの潜在的問題はReactを効率的に使うためには重要じゃない。でも、もしどうやって動いているか深く掘り下げることが好きなら面白いかもね
これが最初のやつ。
私は人生で
super(props)
何度も書いたよclass Checkbox extends React.Component { constructor(props) { super(props); this.state = { isOn: true }; } // ... }
class fields proposal
なら儀式(constructor)をスキップできる。class Checkbox extends React.Component { state = { isOn: true }; // ... }
React 0.13
がプレーンクラスのサポートを追加したとき、こんな感じの構文が計画されていたよ。コンストラクタの定義とsuper(props)
の呼び出しは常にクラスフィールドが人間工学に基づいた代替手段を提供するまでの一時的な解決策だった。でも、ES2015の機能のみを使って例に戻りましょう。
class Checkbox extends React.Component { constructor(props) { super(props); this.state = { isOn: true }; } // ... }
props
を呼ばなかったらなにが起こるんですか?他に何か議論はありますか?確認してみましょう。JavaScriptではsuperは親クラスのコンストラクタを参照します。(この例では、親クラスはReact.Component実装を指しています。)
重要なのは、JavaScriptはあなたがコンストラクターで親のコンストラクターを呼ぶまで
this
は使わせてくれません。class Checkbox extends React.Component { constructor(props) { // �� `this` はまだ使えない super(props); // ✅ 今なら使える this.state = { isOn: true }; } // ... }
class Person { constructor(name) { this.name = name; } } class PolitePerson extends Person { constructor(name) { this.greetColleagues(); // �� ここでは許可されていない, 下記をご確認ください super(name); } greetColleagues() { alert('Good morning folks!'); } }
super
の前にthis
の使用が許可されていた場合のことを想像してみてください。一ヶ月後、
greetColleagues
のメッセージに人の名前を入れるかもしれません。greetColleagues() { alert('Good morning folks!'); alert('My name is ' + this.name + ', nice to meet you!'); }
this.greetColleagues()
はsuper()
の前に呼ばれていることを忘れちゃいました。そう、this.name
はまだ定義されていません!ご覧のとおり、このようなコードは考えるのが非常に難しいのです。
この落とし穴を避けるために Javascriptはコンストラクターでthisを使いたい場合に
super
の呼び出しを強制します。そして、この制限はクラス定義されたReactのコンポーネントにも適用されます。
constructor(props) { super(props); // ✅ ここから`this`が使える this.state = { isOn: true }; }
React.Component
でコンストラクターがthis.props
を初期化するために、props
をsuper
に渡すことが必要と思うかもしれません。// React内部 class Component { constructor(props) { this.props = props; // ... } }
しかし、どういうわけか引数(
props
)なしのsuper()
で呼び出しても、this.props
にrender
や他のメソッド内でアクセスできます。(信じないなら試してみて!)どうやって動いているんだ?
Reactも
props
をコンストラクターを呼んだ後にインスタンスに割り当てていることがわかる// React内部 const instance = new YourComponent(props); instance.props = props;
props
をsuper
に渡し忘れても、Reactはprops
を設定します。これには理由があります。Reactがclassをサポートしたとき、ES6のクラスだけをサポートしたのではありません。
ゴールはより広いクラスの抽象概念をサポートすることでした。
コンポーネントを定義するのにClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScriptや他の方法がどれほど成功するのかは不明確でした。
だからES6のclassで
super()
の呼び出しが必須であるにも関わらず、意図的に固執しませんでした。これは
super(props)
の代わりにsuper()
と書けるということを意味してる?多分そうじゃない。まだ紛らわしい。
確かに、Reactはコンストラクターが実行されたあとに
this.props
を割り当てます。でも、親とあなたのコンストラクターの実行が終わるまでの間、
this.props
は未定義なのです。// React内部 class Component { constructor(props) { this.props = props; // ... } } // あなたのコード class Button extends React.Component { constructor(props) { super(); // �� props渡すの忘れちゃった console.log(props); // ✅ {} console.log(this.props); // �� undefined } // ... }
厳密に必要というわけではないですが、私は常に
super(props)
で渡すことをオススメしています。class Button extends React.Component { constructor(props) { super(props); // ✅ props渡した console.log(props); // ✅ {} console.log(this.props); // ✅ {} } // ... }
this.props
は設定されているということを保証します。長年のReactユーザーは興味があるかもしれないことを最後に少々。
Context APIをclass(古いタイプのcontextTypesもしくはReact 16.6で追加された新しいcontextTypeのどちらでも)内で使用する時、
context
は2つ目の引数としてコンストラクターに渡されることに、気づいているかもしれません。では、
super(props, context)
と書いてみませんか?できますが、contextはそんなに頻繁に利用されないため、この落とし穴はそれほど頻繁に現れません。class fields proposal
ではこの落とし穴はほとんど消えます。明示的なコンストラクタがないと全ての引数は自動的に渡されます。
これはこのような式(
state = {}
)に必要に応じてthis.props
もしくはthis.context
の参照を含めることを許します。Hooksでは
super
もしくはthis
さえ持っていません。しかし、これは別の日の話題としましょう。
コメント
コメントを投稿