見出し画像

【アプリ開発日記47週目】問題演習機能の実装 ~復習編①~

 おはようございます! ちゅーりんです。前回「問題一覧を取得&フィルター&最初の問題ページに遷移」までできたので、今回は

  • 「演習スタート」を押すと最初の問題に遷移、遷移先で「次へ」を押すと次の問題ページに遷移する

  • 全部解き終えると、正答率を表示

  • 終了時に「△×を解き直す」ボタンを表示、その問題だけが入った2周目を始められる

  • 演習中にメイン画面などに戻った場合、「続きから」を選択できる

を実装していきます。

ではさっそく始めていきましょう!

1,問題ページで「次へ」を押すと次の問題へ

 はじめに「現在何問目か」をブラウザ上に保存しておきます。同じくブラウザ上に保存した「問題リスト」から前後の問題のidを取得できるからです。このあと実装する「続きから」でも「前回何問目だったかな」という情報を記憶しておく必要があるので役立ちそうですね。

 ということで、まずlocalStorageに保存。

localStorage.setItem('quiz_list_num', 1);

 さらに、ページ遷移時は敢えてLink(href)ではなく関数によって行います。これで先に「現在何問目か」を更新してから次の問題に進むことができます!

 また、1問目のときは「前の問題に戻る」ボタンを非表示にしたいので、今回は以下のように三項演算子を使いました。

{ prenum != -1 ? <p className='leading-7 cursor-pointer' onClick={goPre}><</p> : <a className='opacity-0'><</a> }

関数

const goPre = e => {
  localStorage.setItem('quiz_list_num', curnum - 1);
  window.location.href = `/quiz/${prenum}`;
}

完成形は以下の通り。無事遷移できていますね!

2,全部解き終えると「正答率」を表示

 さて、今度は時終わった時の処理です。さきほどの場合だと、6問目の時に「次の問題へ」ボタンを押すと遷移しない&モーダルが表示されるようにします。

 最初に、問題を解いて間違えたらブラウザ上に記録が残るようにしましょう。今回もlocalStorageを使います。

// localStorageを更新
const phase = 'bad';
const current_id = location.pathname.split('/')[1];
const miss_list = localStorage.getItem('miss_list');

if (phase == 'normal' || phase == 'bad') {
  if (miss_list) {
    localStorage.setItem('miss_list', `${miss_list}_${current_id}`);
  } else {
    localStorage.setItem('miss_list', current_id);
  }
} else {
  const miss_array = miss_list.split('_');
  let new_list = '';
  for (let i = 0; i < miss_array.length; i++) {
    if (miss_array[i].indexOf(current_id) != -1) new_list += miss_array[i];
  }
  localStorage.setItem('miss_list', new_list);
}

これで保存されるようになりました! ちなみに、子ファイルのuseStateを操作するために今回は

quiz/[id].js(親ファイル)
|- Legends.js(結果の選択コンポ)
|- HistoryList.js (履歴表示&今回の結果を表示)

として親ファイルでLegends.jsの選択が切り替わるのを検知&htmlに書き込み、直後に別の子ファイルである「HistoryList.js内にあるボタンを押す処理」(.click())を実行しました。これで、子ファイルでもhtmlのデータを読み取ってState内に挿入できます。少しややこしいですが。

 そして、最後の問題終了時にlocalStorageに保存したデータを取得して「間違えた問題だけ解き直せる」ようにします!

 作成したモーダル画面がこちら。

 あとは「解いた問題数」「間違えた問題リスト」がわかれば正答率の算出と間違えた問題の解き直しもできそうですね。「間違えた問題リスト」はさきほど実装し、ここに、正解の有無にかぎらず「解いた問題」に+1する処理を付け加えればOKです!

 あとは、最後の問題ページで「次の問題へ」ボタンを押せば……

無事表示されました!! 意外と手間かかった…けど嬉しい機能です!笑

3,終了時に「△×を解き直す」ボタンを表示、その問題だけが入った2周目を始められる

 「正答率が100でないときは解き直しボタンを表示」はシンプルなJSXで書けました。

{ clear_count != solved_count && <p className='btn bg-main bg-main-hover mr-1' onClick={restart}>△と✕を復習</p> }

クリックすると

  • さきほど作成した「miss_list」(間違いリスト)を新たな問題リストとして「quiz_list」に上書き

  • 解いた問題数・ページをリセット

  • 最初の問題を取得し、その問題ページへ遷移

ができれば良さそうです! ということで

const restart = () => {
  const miss_list = localStorage.getItem('miss_list');
  localStorage.setItem('quiz_list', miss_list);
  localStorage.setItem('quiz_list_num', 1);
  localStorage.setItem('solved_count', 0);
  localStorage.setItem('miss_list', '');
  window.location.href = `/quiz/${miss_list.split('_')[0].split('-')[1]}`;
}

間違えた3問だけを抽出して解けるようになりました!

この2周目で間違えた問題も、3周目、4周目…と解き直せます

当時は高知県なんてないんじゃ!土佐藩じゃ!

4,演習中にメイン画面などに戻った場合、「続きから」を選択できる

 さて、演習中に「あかん、デートに遅刻する!」ってなったら大変ですね。それを防ぐ機能を作りましょう。

 と言っても「現在何問目か」などの情報は途中でメイン画面に戻ったりブラウザを閉じても保存されているため、もともと「演習スタート」ボタンでリセットしていた部分を「続きから」ボタンでは取っ払ってしまえばよさそうです。

「はて、localStorageはどれくらい保存されるんだろう?」

と思ったので調べると

・有効期限はない
・sessionStorageはブラウザを閉じると破棄される
・削除は、意図的なブラウザ操作、localStorage.removeItem()やclear()で可能
・文字数制限は、主要なブラウザでは最大5MB(ブラウザにより異なる)
・ただし、javascriptなどでアクセスできてしまうので、パスワードなどの大事な情報は入れないようにする
・対応ブラウザは
Internet Explorer 8、Firefox 3.5、Google Chrome 4 (localStorage)、Google Chrome 5 (sessionStorage)、Opera 10.5、Safari 4

https://1-notes.com/javascript-localstorage/
https://developer.mozilla.org/ja/docs/Web/API/Window/sessionStorage

だそうです!

ということで

この状態で一度戻ってみる
「続きから」を押すと……
ちゃんと同じ問題、3問目に戻ってきました!

おわりに

 今回は問題ページ同士をつなげてきました。演習中に間違えた問題に絞って2週目もできるので、覚えにくい内容も頭に残りやすくなります。

 ですが、このままでは、一度メイン画面に戻ってしまうと間違えた問題だけに絞って解き直すことができません。ということで次回は演習履歴をデータベースに保存&それをもとに、問題選択時に間違えた問題だけに絞れる機能を実装していきます。

 次回は前回と今回の融合ですね! ではでは!


この記事が気に入ったらサポートをしてみませんか?