Rails6でカスタムJavascriptファイル取説

#はじめに
皆さんこんにちは、駆け出しエンジニアのプージニアです！

本記事は以前にRails6環境下の中Javascriptでトグルボタンを実装した際に直面したハマったので
アウトプットも兼ねて導入方法をご紹介させて頂く記事です。

Turbolinksの仕組みを再確認するのにお役に立てるかもしれない記事になっております。

##対象の読者📕
Rails環境下でカスタムしたJavascriptを導入したい方

##参考
3つぐらい導入方法書いてます（僕は１で実装しました）
https://dev.to/morinoko/adding-custom-javascript-in-rails-6-1ke6


#手順１：導入したいカスタムのjsファイルを作成する
まずは./app/javascript配下にカスタムjsファイルを格納するディレクトリcustomを作成します

```
mkdir app/javascript/custom
```

上記で作ったディレクトリ配下に追加したいカスタムjsファイルを作成していきます

今回はTOPページにあるユーザメニューの表示/非表示のトグルボタンを実装する場合を想定して進めます
（読者の方は自分の実装したい機能・用途に合わせた名前つけてください）

user-menu-toggle.jsファイルを先ほどのcustomディレクトリに追加します

```
touch app/javascript/custom/user-menu-toggle.js
```

これで第一段階終了ですね！！

#手順２：(全てのページに反映する機能の場合)
app/javascript/packs/application.jsファイル内で先ほど作成したカスタムjsファイルを読み込む

```js:app>javascript>packs>application.js
require("custom/user-menu-toggle.js")
```
#手順２：(特定のページに反映する場合)
追加したいビューファイル内で読み込む

```erb:hogehoge.erb
<%= javascript_include_tag 'custom/hoge.js' %>
```

Turbolinksをきちんと理解できている方は普通に実装完了したと思います！！

以降は僕がハマった話とTurbolinksの話になるので心配な方以外は読まなくても大丈夫です
#補足：ハマった話とTurbolinksの話
僕自身がTurbolinksの仕組みを分かっていない為以下の例で説明するハマり方をしました😅

以下ソースは僕がポートフォリオのヘッダーにユーザナビゲーションを表示/非表示を切り替えるトグルボタンを実装した物です(アロー関数とごちゃ混ぜすいません笑)

```js:user-menu-toggle.js
  const button = document.getElementById("user-nav-button");
  document.getElementById('user-nav').style.display = 'none'
  // ボタンをクリックしたらナビゲーションの表示の切り替え
  button.addEventListener("click", event => {
    var user_nav = document.getElementById('user-nav')
    userNavToggle(user_nav)
  });
  // ユーザナビ表示切り替えの関数
  function userNavToggle(user_nav){
    if(user_nav.style.display === 'none'){
      user_nav.style.display = 'flex';
    } else {
      user_nav.style.display = 'none';
    }
  };
```

上記内容で実装するとエラーが起きます。
内容は、style of 'null'と出まして、
原因としてはDomツリー構築前にJavascriptの処理が走っているからだと思います。

上記解決する為にDOM構築後に処理が走るようにします。
具体的にはwindow.onloadで先ほどの処理を中に入れて実装しました。
Turbolinks理解されてる方ならもう気付いてると思います笑

```js:user-menu-toggle.js
//window.onloadを追加してDom構成後処理をさせる
window.onload = function() {

  const button = document.getElementById("user-nav-button");
  document.getElementById('user-nav').style.display = 'none'
  // ボタンをクリックしたらナビゲーションの表示の切り替え
  button.addEventListener("click", event => {
    var user_nav = document.getElementById('user-nav')
    userNavToggle(user_nav)
  });
  // ユーザナビ表示切り替えの関数
  function userNavToggle(user_nav){
    if(user_nav.style.display === 'none'){
      user_nav.style.display = 'flex';
    } else {
      user_nav.style.display = 'none';
    }
  };
};
```

TOPページで確認すると無事切り替わることが確認できました〜
しかし、、、違うページに移動した後２度とユーザメニューを表示することはできませんでした。。。

なぜこのような挙動になるかを調べました〜
何とTurbolinksには自身の処理の状態に応じてイベントを発行するようになっているとのことです！！
そして、今回はページ遷移時や表示する際にユーザメニューを閉じてトグルボタンをスタートさせる為にも、
「turbolinks:load」を採用しました。
このイベントは初回のページ表示時やTurbolinksによりページが遷移した時に発火します

改修したコードが下記です。

```js:user-menu-toggle.js
document.addEventListener("turbolinks:load", function() {
  const button = document.getElementById("user-nav-button");
  document.getElementById('user-nav').style.display = 'none'
  // ボタンをクリックしたらナビゲーションの表示の切り替え
  button.addEventListener("click", event => {
    var user_nav = document.getElementById('user-nav')
    userNavToggle(user_nav)
  });
  // ユーザナビ表示切り替えの関数
  function userNavToggle(user_nav){
    if(user_nav.style.display === 'none'){
      user_nav.style.display = 'flex';
    } else {
      user_nav.style.display = 'none';
    }
  };
});

```

以上がTurbolinksにハマった僕の経験談でした〜
同じようにハマった方がいたら役に立つかもしれませんね😅
Turbolinksへの理解の甘さが今回のハマった要因でした笑

#おわりに
最後まで記事を読んで頂きありがとうございました〜
今回の内容のような僕がポートフォリオを作るにあたってハマった内容と
解決までに到る過程を書いて行こうと思っております！

少しでもよかったらLGTM押してください！僕のQiitaへのモチベ上がります〜
よろしくお願いします😁