5.2 KiB
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
5a24c314108439a4d4036174 | クラスメソッドに 'this' をバインドする | 6 | 301379 | bind-this-to-a-class-method |
--description--
state
の設定と更新に加えて、コンポーネントクラスのメソッドを定義することもできます。 クラスメソッドでは通常、メソッドのスコープ内でクラスのプロパティ (state
や props
など) にアクセスできるように、this
キーワードを使用する必要があります。 いくつかの方法でクラスメソッドから this
にアクセスすることができます。
よく使用される方法として、コンストラクターで this
を明示的にバインドすることができます。この場合、コンポーネントの初期化時に this
がクラスメソッドにバインドされます。 気づいたかもしれませんが、前回のチャレンジでは this.handleClick = this.handleClick.bind(this)
をコンストラクターの handleClick
メソッドに使用しました。 その後、クラスメソッドの中で this.setState()
のように関数を呼び出すと、this
はクラスを参照し、undefined
ではなくなります。
注: this
キーワードは JavaScript で特に混乱を招くものの一つですが、React では重要な役割を果たしています。 ここでの動作はまったくふつうですが、今回のレッスンでは this
についての詳しい復習はしません。詳細な説明が必要な方は他のレッスンを参照してください。
--instructions--
コードエディターに、テキストを追跡する state
を持つコンポーネントがあります。 また、テキストを You clicked!
に設定できるメソッドがあります。 ただし、使用している this
キーワードが未定義であるため、このメソッドは動作しません。 コンポーネントのコンストラクターで this
を handleClick()
メソッドに明示的にバインドして修正してください。
次に、render メソッドの button
要素に click ハンドラーを追加してください。 このハンドラーでは、ボタンが click イベントを受け取ったときに handleClick()
メソッドをトリガーする必要があります。 onClick
ハンドラーに渡すメソッドには中括弧を付けて、JavaScript として直接解釈されるようにする必要があることに注意してください。
上記の手順を完了すると、ボタンをクリックしたときに You clicked!
と表示することができます。
--hints--
MyComponent
から、ボタンと h1
要素の 2 つの要素をこの順序で囲む div
要素を返します。
assert(
Enzyme.mount(React.createElement(MyComponent)).find('div').length === 1 &&
Enzyme.mount(React.createElement(MyComponent))
.find('div')
.childAt(0)
.type() === 'button' &&
Enzyme.mount(React.createElement(MyComponent))
.find('div')
.childAt(1)
.type() === 'h1'
);
キーと値のペア { text: "Hello" }
を使用して MyComponent
の state を初期化します。
assert(
Enzyme.mount(React.createElement(MyComponent)).state('text') === 'Hello'
);
button
要素がクリックされたら、handleClick
メソッドを実行し、state の text
を You clicked!
に設定します。
async () => {
const waitForIt = (fn) =>
new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 250));
const mockedComponent = Enzyme.mount(React.createElement(MyComponent));
const first = () => {
mockedComponent.setState({ text: 'Hello' });
return waitForIt(() => mockedComponent.state('text'));
};
const second = () => {
mockedComponent.find('button').simulate('click');
return waitForIt(() => mockedComponent.state('text'));
};
const firstValue = await first();
const secondValue = await second();
assert(firstValue === 'Hello' && secondValue === 'You clicked!');
};
--seed--
--after-user-code--
ReactDOM.render(<MyComponent />, document.getElementById('root'))
--seed-contents--
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "Hello"
};
// Change code below this line
// Change code above this line
}
handleClick() {
this.setState({
text: "You clicked!"
});
}
render() {
return (
<div>
{ /* Change code below this line */ }
<button>Click Me</button>
{ /* Change code above this line */ }
<h1>{this.state.text}</h1>
</div>
);
}
};
--solutions--
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "Hello"
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
text: "You clicked!"
});
}
render() {
return (
<div>
<button onClick = {this.handleClick}>Click Me</button>
<h1>{this.state.text}</h1>
</div>
);
}
};