それ、ちゃんとOnClickに渡せてるん?
それ、ちゃんとOnClickに渡せてるん?:
舐めた題名にしてしまってすみません。
Reactを学び始めてから1年弱が経ちましたが、思い返して見れば慣れるまでは結構苦労しました。。
で、最近になって、なんで慣れるのに苦労したんだろう?と考えたのですが、その原因がStateやPropsといったReact自体の基本的な事というよりはES6の書き方なのではないか、と考えました。
特に、慣れていないとES6のアロー関数とそれに関わるReactのイベントハンドラは少し理解しづらいのではないか?と思うのでこのアドベントカレンダーを機に記事にしてみた次第です。
突然ですが、問題です。以下のうち、実際に文字をクリックした時に動く(consoleで「動いた!」と出力される)のはどれでしょう?(create-react-appした後にApp.jsの中身を消して以下のコードを貼り付ければ確認できます。)
↓yarn startしたらこうなります。
正解は、 問1、問3、問5です。
アロー関数自体の説明は以下のQiitaのサイトがわかりやすかったです。(省略します)
https://qiita.com/mejileben/items/69e5facdb60781927929
https://qiita.com/may88seiji/items/4a49c7c78b55d75d693b
ここで強調したいのは、
というアロー関数があった時、funcは(無名)関数です。func()は関数の本体(この場合はconsole.log("fuga"))です。つまり、func()はそれが読まれた時点で実行されます。
この事と、javascriptのイベントハンドラには関数が渡されることを考えると、、、
引数を渡したい時によくあるミスとして、例えば、
としがちなのですが、これはfuncに引数として"動いた!"を渡して即実行を意味するので、意図した挙動とはなりません。
これを解決するには2通りの方法があります。
のようにすればいけます(先ほどの3番目のパターン)。
func("動いた!")で実行しているものの、その中身が () => console.log(str) の匿名関数なのclick時に無事実行されます。(わかりやすさとしては一つ目の方がいいとは思いますが。。。)
イベントハンドラに複数の関数を渡すことはできません。なので、呼ばれた際に二つの関数が実行される関数を一つ渡します。
イベントハンドラ、と言った割にonClickしか扱わなかったものの、他も基本的には同じです。
ES6に関しては、慣れていないと気持ち悪いと思われがちですが、簡潔に書けてかなり便利です。ES6の便利機能はまた後日記事にしようと思います。
アドベントカレンダー、明日の人は頑張ってください!!
舐めた題名にしてしまってすみません。
Reactを学び始めてから1年弱が経ちましたが、思い返して見れば慣れるまでは結構苦労しました。。
で、最近になって、なんで慣れるのに苦労したんだろう?と考えたのですが、その原因がStateやPropsといったReact自体の基本的な事というよりはES6の書き方なのではないか、と考えました。
特に、慣れていないとES6のアロー関数とそれに関わるReactのイベントハンドラは少し理解しづらいのではないか?と思うのでこのアドベントカレンダーを機に記事にしてみた次第です。
問題
突然ですが、問題です。以下のうち、実際に文字をクリックした時に動く(consoleで「動いた!」と出力される)のはどれでしょう?(create-react-appした後にApp.jsの中身を消して以下のコードを貼り付ければ確認できます。)import React, { Component } from "react";
class App extends Component {
arrowFunc1 = () => console.log("動いた!hoge!");
arrowFunc2 = () => console.log("動いた!fuga!");
arrowFunc3 = () => console.log("動いた!ワン!");
arrowFunc4 = () => console.log("動いた!ニャー!");
render() {
return (
<div style={{ textAlign: "center" }}>
<br />
<br />
<span onClick={this.arrowFunc1}>問1</span>
<br />
<br />
<span onClick={this.arrowFunc2()}>問2</span>
<br />
<br />
<span onClick={() => this.arrowFunc3()}>問3</span>
<br />
<br />
<span
onClick={function() {
this.arrowFunc4();
}}
>
問4
</span>
<br />
<br />
<span
onClick={function() {
console.log("動いた!メー!");
}}
>
問5
</span>
</div>
);
}
}
export default App;
正解は、 問1、問3、問5です。
解説
アロー関数自体の説明は以下のQiitaのサイトがわかりやすかったです。(省略します)https://qiita.com/mejileben/items/69e5facdb60781927929
https://qiita.com/may88seiji/items/4a49c7c78b55d75d693b
ここで強調したいのは、
const func = () => console.log("aaa")
この事と、javascriptのイベントハンドラには関数が渡されることを考えると、、、
- onClickにarrowFunc1という関数を渡せているので、click時に正しく動きます。
- onClickにarrowFunc2()という本体を渡してしまっているので、呼ばれた段階で実行されます。つまり、"動いた!fuga!"がrenderされた段階で走ってしまい、その後、クリックしても聞きません。
- onClickに() => (関数の本体)という関数を渡しているので、click時に正しく動きます。
- onClickに関数を渡しているものの、のthisがAppオブジェクトを指しておらずundefinedとなるため、click時にエラーになります。
- onClickに関数を渡しているので、click時に正しく動きます。
関数に引数を渡したい場合
引数を渡したい時によくあるミスとして、例えば、const func = str => console.log(str)
<span onClick ={func("動いた!")} />
これを解決するには2通りの方法があります。
1つめ
const func = str => console.log(str)
<span onClick = {() => func("動いた!")} />
2つめ
const func = str => () => console.log(str)
<span onClick = {func("動いた!")} />
onClickに複数の関数を渡したい場合
イベントハンドラに複数の関数を渡すことはできません。なので、呼ばれた際に二つの関数が実行される関数を一つ渡します。const func1 = () => console.debug("動いた!")
const func2 = (str) => console.debug(str)
<span
onClick={() => {
func1();
func2("動いた!yeah!");
}}
>
最後に
イベントハンドラ、と言った割にonClickしか扱わなかったものの、他も基本的には同じです。ES6に関しては、慣れていないと気持ち悪いと思われがちですが、簡潔に書けてかなり便利です。ES6の便利機能はまた後日記事にしようと思います。
アドベントカレンダー、明日の人は頑張ってください!!
コメント
コメントを投稿