Reactフックでカウントダウンタイマーを作成する方法
序章
このチュートリアルでは、Reactフックを使用してカウントダウンタイマーを作成し、Reactコンポーネントの状態を更新して副作用を管理します。
Reactフックを使用すると、よりクリーンなコード、コンポーネント間で再利用可能なロジックを作成し、クラスなしで状態を更新できます。
カウントダウンタイマーは一般的なUIコンポーネントです。 ユーザーは、何かをしている時間や、イベントが発生するまでの時間をユーザーに伝えることができます。 このチュートリアルでカウントダウンするイベントは、DigitalOceanのHacktoberfestです。
このチュートリアルの終わりまでに、ReactのuseState()
およびuseEffect()
フックを使用した機能的で再利用可能なカウントダウンタイマーができあがります。
前提条件
このガイドを開始する前に、次のものが必要です。
- Node.jsを実行する開発環境が必要になります。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはのPPAを使用したインストール]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。
- このチュートリアルでは、 Create ReactAppを使用してアプリを作成します。 Create React Appを使用してアプリケーションをインストールする手順については、 CreateReactAppを使用してReactプロジェクトを設定する方法を参照してください。
- また、 JavaScriptでコーディングする方法にあるJavaScriptの基本的な知識と、HTMLおよびCSSの基本的な知識も必要です。 HTMLとCSSの便利なリソースは、 Mozilla DeveloperNetworkです。
このチュートリアルは、Node.js v16.13.1、npm
v8.2.0、およびreact
v17.0.2で検証されました。
ステップ1—空のプロジェクトを作成する
このステップでは、 Create ReactAppを使用して新しいプロジェクトを作成します。 次に、プロジェクトをブートストラップするときにインストールされるサンプルプロジェクトと関連ファイルを削除します。
まず、新しいプロジェクトを作成します。 ターミナルで次のスクリプトを実行し、create-react-app
を使用して新しいプロジェクトをインストールします。
npx create-react-app react-hooks-timer
プロジェクトが終了したら、次のディレクトリに移動します。
cd react-hooks-timer
新しいターミナルタブまたはウィンドウで、 CreateReactApp開始スクリプトを使用してプロジェクトを開始します。 ブラウザは変更時に自動更新されるため、作業中はこのスクリプトを実行したままにします。
npm start
ローカルで実行されているサーバーを取得します。 プロジェクトがブラウザウィンドウで開かなかった場合は、http://localhost:3000/
で開くことができます。 これをリモートサーバーから実行している場合、アドレスはhttp://your_server_ip:3000
になります。
ブラウザには、CreateReactAppによって生成されたReactアプリケーションが読み込まれます。
新しいカスタムコンポーネントのセットを作成するので、空のプロジェクトを作成できるように、ボイラープレートコードをクリアすることから始める必要があります。
まず、テキストエディタでsrc/App.js
を開きます。 これは、ページに挿入されるルートコンポーネントです。 すべてのコンポーネントはここから始まります。 App.js
の詳細については、 Create ReactAppを使用してReactプロジェクトをセットアップする方法を参照してください。
次のコマンドでsrc/App.js
を開きます。
nano src/App.js
次のようなファイルが表示されます。
react-hooks-timer / src / App.js
import React from 'react'; import logo from './logo.svg'; import './App.css'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;
次に、return
ステートメントのすべてを置き換えて、<div>
タグのセットを返します。 これにより、何も返さない有効なページが表示されます。 最終的なコードは次のようになります。
react-hooks-timer / src / App.js
import React from 'react'; import logo from './logo.svg'; import './App.css'; function App() { return ( <div> </div> ) } export default App;
次に、ロゴを削除します。 import logo from './logo.svg';
の行を削除します。
テキストエディタを保存して終了します。
最後に、このアプリケーションでは使用しないため、ロゴを削除します。 混乱を避けるために、作業中に未使用のファイルを削除することをお勧めします。
ターミナルウィンドウで、次のコマンドを入力します。
rm src/logo.svg
プロジェクトが設定されたので、最初のコンポーネントを作成できます。
ステップ2—残り時間を計算する
このステップでは、現在の日付からHacktoberfestの初日までの残り時間を計算する関数を作成します。
まず、calculateTimeLeft
という関数を設定します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { }; // ...
次に、関数内で、JavaScript Date
オブジェクトを使用して、現在のyear
を検索します。
JavaScriptdate
メソッドDate.getFullYear()
に設定されるyear
という変数を作成します。
calculateTimeLeft
関数内に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { let year = new Date().getFullYear(); } // ...
注: JavaScript Date
オブジェクトを使用して、日付と時刻を操作できます。
Date.getFullYear()
メソッドは今年を取得します。
これで、この変数を使用して、現在の日付とHacktoberfestの初日の差を計算できます。
calculateTimeLeft
関数内に、difference
という新しい変数を追加します。 次のコードを使用して、新しいDate
オブジェクトと等しくなるように設定します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { let year = new Date().getFullYear(); const difference = +new Date(`10/01/${year}`) - +new Date(); } // ...
新しいDate
オブジェクトの前の+
は、JavaScriptにオブジェクトを整数としてキャストするように指示する省略形です。これにより、エポックからのマイクロ秒で表されるオブジェクトのUnixタイムスタンプが得られます。
注:このチュートリアルでは、カウントダウンする日付が将来設定されていることを確認してください。設定されていない場合、エラーが発生します。
コードを再利用可能に保つには、 JavaScript Template Literal を使用し、Hacktoberfestの月日とともにyear
変数を追加します。 Hacktoberfestは毎年10月1日に始まります。 ハードコードされた年の代わりにyear
変数を使用すると、常に現在の年になります。
カウントダウンタイマーが切れるまでの合計ミリ秒数を計算したので、ミリ秒数をより親しみやすく人間が読める形式に変換する必要があります。
ステップ3—日、時間、分、秒にフォーマットする
このステップでは、timeLeft
という空のオブジェクトを作成し、if
ステートメントを使用して残り時間があるかどうかを確認し、数学を使用して時間、分、秒の合計数を計算しますおよびモジュラス(%
)演算子。 最後に、timeLeft
を返します。
まず、timeLeft
という空のオブジェクトを作成します。このオブジェクトには、if
ステートメントに日、時間、分、秒が入力されます。
calculateTimeLeft
関数内に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { let year = new Date().getFullYear(); let difference = +new Date(`10/01/${year}`) - +new Date(); let timeLeft = {}; } // ...
次に、difference
変数を比較して0
より大きいかどうかを確認するif
ステートメントを作成します。
calculateTimeLeft
関数内に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { let year = new Date().getFullYear(); let difference = +new Date(`10/01/${year}`) - +new Date(); let timeLeft = {}; if (difference > 0) { timeLeft = { days: Math.floor(difference / (1000 * 60 * 60 * 24)), hours: Math.floor((difference / (1000 * 60 * 60)) % 24), minutes: Math.floor((difference / 1000 / 60) % 60), seconds: Math.floor((difference / 1000) % 60) }; } } // ...
このコードでは、日、時間、分、秒の数値を切り捨て、余りを削除して整数値を取得します。 次に、difference
を比較して、0
より大きいかどうかを確認できます。
最後に、コンポーネントの他の場所で値を使用できるように、timeLeft
を返す必要があります。
calculateTimeLeft
関数内に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const calculateTimeLeft = () => { let year = new Date().getFullYear(); let difference = +new Date(`10/01/${year}`) - +new Date(); let timeLeft = {}; if (difference > 0) { timeLeft = { days: Math.floor(difference / (1000 * 60 * 60 * 24)), hours: Math.floor((difference / (1000 * 60 * 60)) % 24), minutes: Math.floor((difference / 1000 / 60) % 60), seconds: Math.floor((difference / 1000) % 60) }; } return timeLeft; } // ...
Hacktoberfestまでの残り時間を計算する関数を作成したので、タイマーを制御および更新するアプリの状態を追加できます。
ステップ4—useState
およびuseEffect
を使用してアプリの状態を更新する
React Hooksを使用すると、既存の機能コンポーネントをクラスに変換せずに、それらに状態管理機能を追加できます。
このステップでは、useState
およびuseEffect
フックをReactからインポートして、このコンポーネントの状態を管理します。
App.js
ファイルの先頭で、インポートステートメントにuseState
とuseEffect
を追加します。
react-hooks-timer / src / App.js
import React, { useEffect, useState } from "react"; // ...
このコードは、Reactから利用できるこれらの特定のフックとその機能を使用することをReactに通知します。
カウントダウンタイマーを機能させるには、状態を更新するために以前にコーディングした残り時間のメソッドを接続する必要があります。
calculateTimeLeft
関数の後に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const [timeLeft, setTimeLeft] = useState(calculateTimeLeft()); // ...
このJavaScript構文は、 arraydestructuringと呼ばれます。
useState
メソッドは、初期状態を設定するパラメーターを受け取り、現在の状態を含む配列と状態を設定する関数を返します。
timeLeft
は、間隔の残り時間オブジェクトを運び、状態を設定するメソッドを提供します。 コンポーネントのロード時に、timeLeft
値は現在の残り時間の値に設定されます。
次に、useEffect
フックを使用して、コンポーネントの副作用に対処します。
注: 副作用は、実行されている関数の範囲外の何かに影響を与えるものです。
このソリューションでは、useEffect
フック内でsetTimeout
メソッドを使用します。 setTimeout
および同様のsetInterval
メソッドは、useEffect
フック内で使用される場合の一般的なReactパターンです。
ReactのsetTimeout
メソッドのようなほとんどの非同期動作は、useEffect
フックとuseState
フックの組み合わせで定義されます。
注: React Docs のこのセクションで、setTimeout
やsetInterval
などのメソッドをいつどのように使用するかについて詳しく読むことができます。
useState()
関数の後に次のコードを追加します。
react-hooks-timer / src / App.js
// ... const [timeLeft, setTimeLeft] = useState(calculateTimeLeft()); useEffect(() => { const timer = setTimeout(() => { setTimeLeft(calculateTimeLeft()); }, 1000); }); // ...
useEffect
は、残り時間を更新するものです。 デフォルトでは、Reactはレンダリングのたびにエフェクトを再呼び出しします。
変数timeLeft
が状態で更新されるたびに、useEffect
が起動します。 発火するたびに、タイマーを1秒(または1,000ms)に設定します。これにより、その時間が経過した後の残り時間が更新されます。
その後、サイクルは毎秒続きます。
スタックタイムアウトとエラーの原因となる可能性を排除するために、useEffect
フック内にもclearTimeout
メソッドを追加します。
clearTimeout
メソッドを追加し、可変タイマーをパラメーターとして渡します。
react-hooks-timer / src / App.js
// ... useEffect(() => { const timer = setTimeout(() => { setTimeLeft(calculateTimeLeft()); }, 1000); return () => clearTimeout(timer); }); // ...
return
関数は、コンポーネントの最初の実行を除いて、useEffect
がtimer
を実行するたびに実行され、コンポーネントがマウント解除されている場合はタイムアウトをクリアします。
状態がcalculateTimeLeft()
オブジェクトに設定され、エフェクトフック内で更新されているので、これを使用してディスプレイコンポーネントを構築できます。
ステップ5—Object.keys
を使用する
このステップでは、Object.keys
を使用して、timeLeft
オブジェクトを反復処理し、表示コンポーネントを構築します。 表示コンポーネントを使用して、Hacktoberfestが始まるまでの残り時間を表示します。
まず、useEffect
フックの下にtimerComponents
という名前の新しい変数を作成します。
react-hooks-timer / src / App.js
// ... const timerComponents = []; // ...
timeLeft
のキーを繰り返し処理した後、この変数を使用して、残り時間で新しいJSXコンポーネントをプッシュします。
次に、 Object.keys を使用して、calculateTimeLeft
関数から返されたtimeLeft
オブジェクトを反復処理します。
このコードをtimerComponents
変数に追加します。
react-hooks-timer / src / App.js
// ... const timerComponents = []; Object.keys(timeLeft).forEach((interval) => { if (!timeLeft[interval]) { return; } timerComponents.push( <span> {timeLeft[interval]} {interval}{" "} </span> ); }); // ...
ここで、コードはtimeLeft
オブジェクトのプロパティをループします。 タイマー間隔の値がゼロより大きい場合、timerComponents
配列に要素が追加されます。
注:コード内の余分な{" "}
は、画面に表示されたときに残り時間を表示する間隔が互いにぶつからないようにするために使用されます。
{}
を使用すると、JSX内でJavaScriptを使用でき、""
でスペースを追加できます。
これで、Appコンポーネントのreturn
ステートメントに新しいJSXを追加して、Hacktoberfestまでの残り時間を表示する準備が整いました。
ステップ6—残り時間を表示する
このステップでは、JSXコンポーネントをアプリコンポーネントのreturn
ステートメントに追加します。 三項演算子を使用して、残り時間があるかどうか、またはHacktoberfestの時間かどうかを確認します。
timerComponents
配列を使用するには、その長さを確認して返すか、タイマーがすでに経過していることをユーザーに通知する必要があります。
return
ステートメント内に次のコードを追加します。
react-hooks-timer / src / App.js
// ... return ( <div> {timerComponents.length ? timerComponents : <span>Time's up!</span>} </div> ); // ...
React JSXコンポーネントでは、JavaScriptif
ステートメントの代わりに三項演算子を使用します。 これは、JSX内では式のみが許可されているためです。
コードのtimerComponents.length
行は、timerComponents
配列内に何かがあるかどうかを確認し、ある場合はそれをレンダリングします。ない場合は、Time's up!
をレンダリングします。
次に、return
ステートメントにさらに2つのJSXコンポーネントを追加して、カウントダウンしているものをユーザーに知らせます。
react-hooks-timer / src / App.js
// ... return ( <div> <h1>Hacktoberfest 2020 Countdown</h1> <h2>With React Hooks!</h2> {timerComponents.length ? timerComponents : <span>Time's up!</span>} </div> ); // ...
2020
をハードコーディングする代わりに現在の年を使用するには、新しい状態変数を作成し、初期状態をnew Date().getFullYear();
に設定します。
最初のuseState()
変数の後に、次のコードを追加します。
react-hooks-timer / src / App.js
// ... const [timeLeft, setTimeLeft] = useState(calculateTimeLeft()); const [year] = useState(new Date().getFullYear()); // ...
このメソッドは、calculateTimeLeft
関数で使用したように現在の年を取得します。
次に、ハードコードされた2020
をh1
から削除してyear
に置き換えることができます。
react-hooks-timer / src / App.js
// ... return ( <div> <h1>Hacktoberfest {year} Countdown</h1> <h2>With React Hooks!</h2> {timerComponents.length ? timerComponents : <span>Time's up!</span>} </div> ); // ...
これにより、状態変数が表示され、常に現在の年になります。 完成したプロジェクトは次のようになります。
このGitHubリポジトリをチェックして、完全なコードを確認してください。
結論
このチュートリアルでは、useState
およびuseEffect
フックを使用してカウントダウンUIコンポーネントを構築し、アプリケーションの状態を管理および更新しました。
ここから、 Reactコンポーネントのスタイリングを使用して学習を続け、より魅力的なカウントダウンUIを作成できます。
また、DigitalOceanの How To Code in React.js シリーズ全体をフォローして、Reactを使用した開発の詳細を学ぶこともできます。