【Error・学習】JavaScriptクイズアプリ：セッションストレージとページ遷移でハマったポイントと解決策

## はじめに
今回は下記アドベントカレンダーに参加したので個人開発で起こったエラーに対して行ったチャレンジ？についての記事を書きたいと思います。

https://qiita.com/wa-chan222/items/057a97139ab5cfb5c7f0


- 開発環境：**Glitch** を使用。
- 今回は、**JavaScript** を使ってクイズアプリを開発する中で直面した問題とその解決方法を共有します。
- 主に、「セッションストレージを用いたスコアの管理」や「ページ遷移時のデータの保持」に焦点を当てます。



## 問題1: 結果ページへの遷移が意図した通りに動作しない
### 問題のコード
```jsx
function showResults() {
  let count = Number(sessionStorage.getItem("count"));
  if (!count) {
    window.location = "no.html"; // Noの結果ページ
  } else if (count > 4) {
    window.location = "yes.html"; // Yesの結果ページ
  } else if (count > 2) {
    window.location = "maybe.html"; // Maybeの結果ページ
  } else if (count <= 2) {
    window.location = "no.html"; // Noの結果ページ
  }
}
```

- **問題点**:
    - 条件分岐の順序が不適切で、一部の条件がスキップされていました。
    - `!count` は `count` が `0` の場合にも真と評価され、誤ったページに遷移する可能性がありました。

### 修正後のコード
```jsx
function showResults() {
  let count = Number(sessionStorage.getItem("count"));
  console.log("Current count value: ", count); // デバッグ用のログ
  if (count > 4) {
    window.location = "yes.html"; // Yesが多い
  } else if (count > 2) {
    window.location = "maybe.html"; // 中間
  } else {
    window.location = "no.html"; // Noが多い
  }
}
```
- **修正ポイント**:
    1. 条件の順序を整理。
    2. デフォルト値の設定や `console.log` を追加し、デバッグを容易に。

---

## 問題2: ページ遷移時にスコアが正しく保存されない
### 問題のコード
```html
<a href="q2.html" onclick="incToo();" class="yes-button">👍</a>
<a href="q2.html" onclick="decToo();" class="no-button">👎</a>
```

- **問題点**:
    - クリック時のページ遷移がスコアの保存処理より先に実行されることがあり、`sessionStorage` にデータが正しく保存されない。

### 修正後のコード
```html
<a href="q2.html" onclick="incToo(); event.preventDefault();" class="yes-button">👍</a>
<a href="q2.html" onclick="decToo(); event.preventDefault();" class="no-button">👎</a>
```

- **修正ポイント**:
    1. `event.preventDefault()` を追加して、リンクのデフォルト動作を抑制。
    2. 保存処理後に明示的にページ遷移させる関数を導入（詳細は以下）。

---

## 問題3：カウントの初期化処理を改善
修正前のコードでは、`count` が `0` 以外の値でも誤動作する可能性がありました。
これを以下のように修正しました
- **修正前**
    ```jsx
    if (!count) {
      count = 0;
    }
    ```
    
- **修正後**
    ```jsx
    if (isNaN(count) || count === null) {
      count = 0; // 初期化
    }
    ```
この変更により、`count` が数値でない場合（例：`NaN` や `null`）でも確実に初期値が設定することができました。


## おまけ1: ページ遷移を管理する共通関数を導入
ページ間の遷移を管理する処理を共通化し、コードの重複を減らしました

```jsx
// ページ遷移を管理する共通関数
function navigateToNextPage() {
  // 現在のページのファイル名を取得
  const currentPage = window.location.pathname.split("/").pop();

  // 次のページを設定
  const nextPages = {
    "q1.html": "q2.html",
    "q2.html": "q3.html",
    "q3.html": "q4.html",
    "q4.html": "q5.html",
    "q5.html": "q6.html",
    "q6.html": "results.html" // 最終ページから結果ページへ
  };

  const nextPage = nextPages[currentPage];

  // 次のページへ遷移
  if (nextPage) {
    setTimeout(() => {
      window.location = nextPage;
    }, 200); // 0.2秒後に遷移
  }
}
```


## おまけ2：セッションストレージの処理部分の解説
セッションストレージは、ユーザーがブラウザを閉じるまでデータを保存できる場所です。
ページ間でデータをやり取りするために使います。
今回のコードでは、ユーザーが「👍」や「👎」を選択した結果（count）を保存し、次のページに進む際にその情報を使用します。
以下がセッションストレージを使ってカウントを管理する部分になります
### **カウントをインクリメントする処理 (選択肢が「👍」のとき)**
```java
function incToo(event) {
  event.preventDefault(); // デフォルトのリンク動作をキャンセル

  let count = Number(sessionStorage.getItem("count")); // セッションストレージから count を取得
  if (isNaN(count) || count === null) {
    count = 0; // 初期化（count が NaN または null の場合）
  }
  count++; // インクリメント
  sessionStorage.setItem("count", count); // 新しい count をセッションストレージに保存

  navigateToNextPage(); // 次のページに遷移
}
```

- `sessionStorage.getItem("count")` で現在のカウントを取得し、`count` が `NaN`（数値でない）や `null`（データがない）場合は、初期値 `0` を設定します。
- その後、`count` を `1` 増やし、`sessionStorage.setItem("count", count)` で新しい値をセッションストレージに保存します。

### **カウントをデクリメントする処理 (選択肢が「👎」のとき)**
```java
function decToo(event) {
  event.preventDefault(); // デフォルトのリンク動作をキャンセル

  let count = Number(sessionStorage.getItem("count")); // セッションストレージから count を取得
  if (isNaN(count) || count === null) {
    count = 0; // 初期化（count が NaN または null の場合）
  }
  count--; // デクリメント
  sessionStorage.setItem("count", count); // 新しい count をセッションストレージに保存

  navigateToNextPage(); // 次のページに遷移
}
```

この処理もインクリメントと同様に、現在のカウントを取得し、count をデクリメント（減らす）して、更新されたカウントをセッションストレージに保存します。

### **`showResults` 関数でのセッションストレージの使用**
最後に、ユーザーが選択した結果に基づいて遷移するページを決定する部分です
```java
function showResults() {
  let count = Number(sessionStorage.getItem("count")); // セッションストレージから count を取得
  console.log("Current count value: ", count); // 現在の count をコンソールに表示
  if (count > 4) {
    window.location = "yes.html"; // count が 5 より大きい場合、Yes のページに遷移
  } else if (count > 2) {
    window.location = "maybe.html"; // count が 3 より大きく、5 以下の場合、Maybe のページに遷移
  } else {
    window.location = "no.html"; // count が 2 以下の場合、No のページに遷移
  }
}
```
`sessionStorage.getItem("count")` で保存されたカウント値を取得し、その値に基づいて遷移先のページを決定しています。



## さいごに
JavaScript を使ったクイズアプリの開発中に直面した問題について、その原因と解決策を具体的に紹介しました。
セッションストレージを使ったスコアの管理や、ページ遷移時のデータ保持における工夫について触れながら、コードの改善プロセスを解説しました。
この内容が、同じような課題に取り組む方々の参考になれば幸いです。