【ITニュース解説】How I Built a Retro Terminal Panel in React
2025年09月06日に「Dev.to」が公開したITニュース「How I Built a Retro Terminal Panel in React」について初心者にもわかりやすいように丁寧に解説しています。
ITニュース概要
Reactでレトロなターミナル風画面を作る方法を紹介。`useState`で表示内容を管理し、`useEffect`でコマンドや出力が1行ずつ表示されるアニメーションと点滅カーソルを実装する。CSSでネオングリーン文字などレトロな見た目に仕上げる。Reactの基本機能で動的なUIを構築する具体的な手法がわかる。
ITニュース解説
今回の記事は、Webサイトにレトロなターミナル風の動くパネルをどのように作成したかについて解説している。システムエンジニアを目指す上で、このようなインタラクティブなUI(ユーザーインターフェース)を構築する技術は非常に重要であり、Web開発の基本要素が詰まっているため、初心者にとっても良い学びの機会となるだろう。
このターミナルパネルの目標は、まるで本物のターミナルのようにコマンドとその実行結果を順番に表示し、さらにアニメーションさせることである。また、実際にタイピングしているかのように見える点滅するカーソルや、すべてのコマンドが表示された後に一度リセットされる機能も実装されている。これらはすべて、ReactというJavaScriptのライブラリを使って実現されている。ReactはWebサイトのUIを効率的に構築するための強力なツールであり、現代のWeb開発では広く利用されている。
まず、このターミナルパネルが「今、どの行を表示しているか」という状態を管理するために、Reactの useState という機能が使われている。useState は、Reactコンポーネントが持つべきデータ(状態)を定義し、そのデータが変化したときに、コンポーネントが自動的に再描画されるようにするためのフック(Reactの特別な関数)である。ここでは terminalLines という変数に現在表示されている行の配列を格納しており、setTerminalLines という関数を使ってその配列を更新する。この配列が更新されるたびに、ターミナルパネルの表示内容が変わるという仕組みだ。初期状態では空の配列が設定されているため、最初は何も表示されていない。
次に、ターミナルに表示させる具体的な内容が定義されている。これは terminalCommands という名前の配列で、ここにコマンドとそのコマンドに対する出力が順番に文字列として格納されている。例えば、「> whoami」というコマンドの後に「ngawang_tenzin」というユーザー名が表示され、「> cat skills.txt」というコマンドの後に「React.js | Node.js | Python | TypeScript」といったスキル一覧が表示される。このように、表示したいすべての行があらかじめこの配列の中に準備されている。
そして、このパネルの核となるアニメーションのロジックは、Reactの useEffect というフックを使って実装されている。useEffect は、コンポーネントが表示されたとき、更新されたとき、あるいはコンポーネントが画面から消えるときに特定の処理(副作用と呼ばれる)を実行するために使用される。今回の場合は、一定時間ごとに新しい行をターミナルに追加していくという処理が副作用にあたる。
具体的なアニメーションの仕組みは次のようになる。useEffect の中で setInterval というJavaScriptの関数が使われている。setInterval は、指定した時間が経過するたびに特定の処理を繰り返し実行するタイマー機能だ。この記事では、800ミリ秒(0.8秒)ごとに terminalInterval というタイマーが発火し、terminalCommands 配列から次の行を terminalLines に追加する処理を実行している。
lineIndex という変数は、terminalCommands 配列のどのインデックス(何番目の要素)まで表示したかを追跡するために使われる。setInterval が実行されるたびに、lineIndex が指し示す terminalCommands の要素が setTerminalLines 関数を通じて terminalLines 配列に追加され、その後 lineIndex は1つ増やされる。これにより、新しい行が次々とターミナルに表示されていく。
もし lineIndex が terminalCommands 配列の最後の要素を超えた場合、つまりすべてのコマンドと出力が表示され終わった場合、アニメーションは一時停止する。そして、setTimeout という別のJavaScriptのタイマー関数を使って、3秒後にターミナルをリセットする処理が実行される。このリセット処理では、setTerminalLines([]) を実行して terminalLines を空にし、lineIndex も0に戻すことで、ターミナルが初期状態に戻り、再度最初からアニメーションが始まる準備が整う。
また、isRetroMode という状態変数によって、このアニメーションが有効かどうかが制御されている。isRetroMode が真の場合にのみアニメーションが開始され、偽の場合はターミナルがリセットされて何も表示されない状態となる。useEffect は、コンポーネントが画面から消える際や、特定の依存関係が変更された際にクリーンアップ処理を実行できる。今回の場合は、terminalInterval が設定されている場合に clearInterval(terminalInterval) を呼び出すことで、タイマーが不要になったときに適切に停止させ、メモリリークなどの問題を避けている。これは、不要な処理がバックグラウンドで動き続けることを防ぐための重要なプラクティスである。
最後に、見た目のデザイン、つまりスタイリングにはCSSが使われている。CSS(Cascading Style Sheets)は、Webページの要素がどのように表示されるかを記述するための言語だ。このターミナルパネルでは、ネオングリーンのテキスト、暗い背景色、そして点滅するカーソルといったレトロな雰囲気を出すためにCSSが活用されている。
具体的には、コマンドの行には .terminal-line.command クラスが適用され、color: #00ff41; というネオングリーンが設定されている。出力の行には .terminal-line.output クラスが適用され、少し控えめなグレー (#cccccc) に設定され、さらに margin-left: 1rem; で少しインデント(字下げ)されているため、コマンドと出力が視覚的に区別しやすいようになっている。
点滅するカーソルの実現には、CSSの animation プロパティと @keyframes ルールが使われている。.terminal-cursor クラスには、animation: blink 1s infinite; というプロパティが設定されており、blink という名前のアニメーションが1秒かけて無限に繰り返されることを意味する。@keyframes blink の定義では、アニメーションの開始時(0%)と中間点(50%)では要素の透明度(opacity)を 1(完全に不透明)にし、それ以外の時間(51%から100%)では 0(完全に透明)にすることで、カーソルが点滅しているように見せている。
このようにして、Reactの状態管理機能、アニメーションロジック、そしてCSSによるスタイリングを組み合わせることで、動的でアニメーションするレトロなターミナルパネルが構築されている。このプロジェクトは、Reactの useState と useEffect の基本的な使い方、JavaScriptのタイマー機能、そしてCSSによる視覚的な表現方法を学ぶのに最適な例である。これらの技術は、Webアプリケーション開発において非常に広く使われているため、システムエンジニアを目指す上で確実に身につけておくべき重要なスキルと言えるだろう。