それ、ちゃんとOnClickに渡せてるん?

それ、ちゃんとOnClickに渡せてるん?:

舐めた題名にしてしまってすみません。

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; 
 
↓yarn startしたらこうなります。



スクリーンショット 2018-12-19 21.33.39.png


正解は、 問1問3問5です。


解説

アロー関数自体の説明は以下のQiitaのサイトがわかりやすかったです。(省略します)

https://qiita.com/mejileben/items/69e5facdb60781927929
https://qiita.com/may88seiji/items/4a49c7c78b55d75d693b

ここで強調したいのは、

const func = () =>  console.log("aaa") 
というアロー関数があった時、funcは(無名)関数です。func()は関数の本体(この場合はconsole.log("fuga"))です。つまり、func()はそれが読まれた時点で実行されます。

この事と、javascriptのイベントハンドラには関数が渡されることを考えると、、、

  1. onClickにarrowFunc1という関数を渡せているので、click時に正しく動きます。
  2. onClickにarrowFunc2()という本体を渡してしまっているので、呼ばれた段階で実行されます。つまり、"動いた!fuga!"がrenderされた段階で走ってしまい、その後、クリックしても聞きません。
  3. onClickに() => (関数の本体)という関数を渡しているので、click時に正しく動きます。
  4. onClickに関数を渡しているものの、のthisがAppオブジェクトを指しておらずundefinedとなるため、click時にエラーになります。
  5. onClickに関数を渡しているので、click時に正しく動きます。


関数に引数を渡したい場合

引数を渡したい時によくあるミスとして、例えば、

const func = str => console.log(str) 
 
<span onClick ={func("動いた!")} /> 
としがちなのですが、これはfuncに引数として"動いた!"を渡して即実行を意味するので、意図した挙動とはなりません。

これを解決するには2通りの方法があります。


1つめ

const func = str => console.log(str) 
 
<span onClick = {() => func("動いた!")} /> 
のようにすればいけます(先ほどの3番目のパターン)。


2つめ

const func = str => () => console.log(str) 
 
<span onClick = {func("動いた!")}  /> 
 
func("動いた!")で実行しているものの、その中身が () => console.log(str) の匿名関数なのclick時に無事実行されます。(わかりやすさとしては一つ目の方がいいとは思いますが。。。)


onClickに複数の関数を渡したい場合

イベントハンドラに複数の関数を渡すことはできません。なので、呼ばれた際に二つの関数が実行される関数を一つ渡します。

const func1 = () => console.debug("動いた!") 
const func2 = (str) => console.debug(str) 
 
<span 
 onClick={() => { 
  func1(); 
  func2("動いた!yeah!"); 
 }} 
> 


最後に

イベントハンドラ、と言った割にonClickしか扱わなかったものの、他も基本的には同じです。

ES6に関しては、慣れていないと気持ち悪いと思われがちですが、簡潔に書けてかなり便利です。ES6の便利機能はまた後日記事にしようと思います。

アドベントカレンダー、明日の人は頑張ってください!!

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)