5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者向け】React/Vite フックについて(useState useEffect)

Last updated at Posted at 2024-09-03

はじめに

こんにちは!
プログラミング初心者のジンです。

私は今Vite(React)にてプロダクト作りに励んでいます。
しかしやはり初心者には難しい!
調べても単語が難しくよくわからない...:frowning2:

そこで初心者の私だからこそつまづいて、調べたことやまとめたことを
同じように悩んだ方向けに届いたらと思い記事にしました。
初心者が書く初心者向け記事として、
少しでも参考になれば幸いです。

Reactのフック(Hooks)とは?

Reactのフック(Hooks)は、関数コンポーネントで状態管理やライフサイクルの機能を利用できるようにするための機能です。これにより、クラスコンポーネントを使わずに、関数コンポーネントだけで複雑なロジックを実装できるようになります。

と、ありますが、、、
もうこの時点で何が何やらわかりませんでした:thinking:
ただ、このフック、コードの読みやすさ向上はもちろん、
勉強していくうちに重要だと気付きました。

現在では16種類?(React 19時点)もあるのだとか、、、。
多いし、使いこなせる自信もない、、、。
むずい。むずすぎる。

というわけで全体的にフックが何をしているかというよりももう少し細かく
このフックは何をしているのか
何個かに分けて勉強し、まとめていくことにします。

useState useEffect の2種紹介

useState useEffectは、初心者プロダクトでは
めちゃよく出てきます。
しかも訳も分からず「なぜか」使えちゃうんです。
某生成AIも多用してくるし、、、
でもそれだけ使われるものなら
理解して使いたいですよね。
※以降 私がつまづいた単語、用途解説は下にまとめて書いているので読み進めていてわからないものあれば下の方を見てみてください!なかったらごめんなさい。

useState

コンポーネント内状態(state)を管理するためのフック。
状態が変更されると、コンポーネントが再レンダリングされます。

簡単な使用目的は
カウンターとして使ったり
フォームの入力管理(入力のリアルタイム管理) ができたりします。

const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>+ボタン</button>

例文は
始めを0としたときに、
ボタンクリックごとにcount数を1増やそう!の機能。

[ 現状の状態 , 変化後の状態 ]
ボタンクリックごとに
[count,setCount]→[0,1]→[1,2]→...

文字でも同じです。

例えば入力フォームに名前を打つ時も
JIN
という名前を打つ時も
[ ,J]→[J,JI]→[JI,JIN]
となってよく見るタイピング入力はReactでは
useStateで実現できるんだ~と学びになりました。

状態管理
がキーワードですね。

useEffect

副作用の処理(データ取得、DOMの操作、タイマー設定など)を行うためのフック。

(筆者)「副作用??え?」となりました。
この副作用、詳しい解説は下のほうに載せますが、
めっちゃざっくりいうと
補佐。

プログラミングのメイン業務を画面表示とするなら
サブ業務をやってくれるイメージ

例 画面読み込み時にデータを持ってくる 5秒後にメッセージ表示等ができる

useEffect(() => {
fetch('/api/data').then(response => setData(response.data));
}, []);

この例文も見てびっくり、初見じゃ何も理解できなかった、、、。

簡単に和訳すると
「画面読み込み時に1度だけAPIにリクエストを送って、返ってきたデータをDataに保存してね」となります。

このuseEffectは画面読み込み時(レンダリング後)や
何らかの操作(動作)のようにメイン業務を終えた後に効果を発揮します。
イメージで私が覚えやすかったのは
ギターのエフェクターでした。:guitar:(名前も似てるし)
いくらつないでもつないでるだけでは弦を弾かないと音は変わるわけないのがミソです。
外的影響がないと効果発揮できないイメージですね。

そしてもう一つ、画面読み込み時1度ってどこに書いてんだよって思いませんか?
これがですね、例文末の

}, [ ]);

のところの

[ ]

になります。
[ ]が空の場合は画面読み込み時に1度という解釈でOKです。
今回の[ ]のことを依存配列といい、
[ ]内が変化するたびにuseEffectも効果を発揮します。
以下は依存配列内に条件がある場合の例文です。

import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);
  const [shouldFetch, setShouldFetch] = useState(false); // トリガー用の状態

  useEffect(() => {
    if (shouldFetch) {
      fetch('/api/data')
        .then(response => response.json())
        .then(data => setData(data))
        .catch(error => console.error('Error fetching data:', error))
        .finally(() => setShouldFetch(false)); // リクエスト完了後、トリガーをリセット
    }
  }, [shouldFetch]); // shouldFetchが変わるたびに実行

  const handleClick = () => {
    setShouldFetch(true); // ボタンを押すとトリガーをオンにする
  };

  return (
    <div>
      <button onClick={handleClick}>更新</button>
      {data && <div>取得したデータ: {JSON.stringify(data)}</div>}
    </div>
  );
}

export default MyComponent;

急に分量増えたように見えるけどここまで読んでるあなたなら
ゆっくり見ればもう大丈夫なはず、
このコードでは更新ボタンを押すたびに依存配列内のshouldFetchが変化し、
useEffect内が実行されるようになります。

※以下上記コードおよび単語補足の後に最後にと続きます。
よかったら最後までお付き合いください!

分からなかった単語・使い方など

レンダリング

データやコードを実際にユーザーが目にする形で表示するプロセスのこと。

コンポーネント

画面をいくつかに分解してコードを書く際のその部分ごと。部品。

ライフサイクル

Reactコンポーネントの「生まれてから消えるまでの一連のプロセス」を指します。具体的には、コンポーネントが作成され、DOMに挿入され、更新され、最後に削除されるまでの一連の流れのこと

副作用

コンポーネントのレンダリングに直接関係しない、外部のデータや動作に影響を与える処理のこと

fetch(Promiseを返す関数)

JavaScriptのビルトイン関数※1で、ネットワークを介してリソース(通常はAPI)を取得するために使用

※1ビルトイン関数(Built-in Functions)とはプログラミング言語にあらかじめ組み込まれている関数

「おいフェッチ、パン買って来いよ。」のイメージかなと。
パシリのフェッチ君はいつも購買に(API)にパン(Data)を買いに行かされるのです。

then

Promise※2のメソッドで、リクエストが成功した場合に実行されるコールバック関数を指定fetchが成功してデータを取得すると、このthenの中に指定された関数が実行されます。
「その時」みたいな意味合いが強いイメージですね。
「パン買えたら(その時は)5分以内で俺のところ戻って来いよ。」

※2 Promise(プロミス)

JavaScriptで非同期処理を扱うためのオブジェクトです。非同期処理とは、時間のかかる処理(例えば、ネットワークリクエストやファイルの読み込みなど)が完了するのを待たずに次のコードを実行するような処理のことです。

Promiseの基本的な概念

  • Pending(保留中): Promiseがまだ完了していない状態。非同期処理が進行中で、最終結果がまだ得られていない段階です。(購買部にダッシュ中)
  • Fulfilled(成功): 非同期処理が成功し、結果が得られた状態。この状態になると、thenメソッドに渡された処理が実行されます。(おつかい終了)
  • Rejected(失敗): 非同期処理が失敗し、エラーが発生した状態。この状態になると、catchメソッドに渡された処理が実行されます。(すみません売り切れでやんす。)

オブジェクト

JavaScriptにおいてキーと値のペアで構成されるデータ構造のこと

  • キー(プロパティ): 各データに対する名前、識別子。通常は文字列で指定されます。
  • : キーに対応するデータ。数値、文字列、配列、別のオブジェクト、関数など、さまざまなデータ型が入ります。
name="John"//(キー=値)

組み合わせとしてはドット記法やブラケット記法

const person = {
    name: "John",
    age: 30,
    isStudent: false,
    greet: function() {
        console.log("Hello, my name is " + [this.name]);
    }
};

のとき ドット記法(関数名.欲しいキー)で値が表示

console.log([person.name]); // "John" を表示

別表記 ブラケット記法(関数名[”キー”])で値が表示

console.log(person["age"]); // 30 を表示

非同期処理

ある処理が完了するのを待たずに、他の処理を同時に進めることができるプログラムの実行方式のことです。これにより、時間のかかる処理(例えば、ネットワーク通信やファイルの読み込み)が終わるのを待たずに、他の処理を続行できます。

同期処理との違い

  • 同期処理: 一つの処理が完了するまで次の処理が開始されない。例えば、A→B→Cという順序で実行される場合、Aが終わるまでBは開始されません。
  • 非同期処理: 一つの処理を実行しながら他の処理も並行して進められる。処理Aが完了するのを待たずに、処理BやCが実行できます。

非同期処理の例

1. 非同期処理の例: setTimeout

console.log("Start"); //A

setTimeout(() => {
  console.log("This is a delayed message");
}, 2000);  //B

console.log("End");  //C

このコードでは、「Start」が表示された後、setTimeoutによって「This is a delayed message」が2秒後に表示され、その間に「End」が表示されます。
A→B→Cが普通だけど今回の場合はA→C→Bの順にconsole.logには出る

2. 非同期処理の例: APIリクエスト

console.log("Fetching data...");

fetch('/api/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

console.log("Request sent");

ここでは、fetch関数が非同期でAPIリクエストを送信します。データが取得される前に「Request sent」が表示され、データが取得された後にその内容が表示されます。
ここでのcatchが先ほどの売り切れでやんす。のところですね。

結果(console.log)

 Fetching data...
 Request sent
データが取得された後に { data } //お待たせでやんす。

非同期処理の利点

  • 効率の向上: ユーザーインターフェースが他の操作に反応し続けることができ、ユーザー体験が向上します。例えば、ウェブページがAPIからデータを取得している間でも、他のボタンやリンクが即座に反応してくれるのでもっさり感の軽減に!

  • リソースの最適化: プログラムが時間のかかるタスクを待つ間に、他の作業を進めることができ、リソースを無駄にしません。

非同期処理はどのようにして書ける?

  • コールバック関数: 処理が完了したときに呼び出される関数を渡します。
  • Promise: 成功時と失敗時の処理を分けて記述できるオブジェクトです。(先ほど解説)

コールバック関数

他の関数に引数として渡される関数のこと

通常、コールバック関数は、特定の処理が完了したときや、イベントが発生したときに呼び出されます。JavaScriptでは、特に非同期処理で頻繁に使われます。

function fetchData(callback) {
// 模擬的なデータ取得
    setTimeout(() => {
        const data = { name: "John", age: 30 };
        callback(data);
    }, 2000);
}

function handleData(data) {
    console.log("取得したデータ:", data);
}

// fetchData関数にhandleDataをコールバックとして渡す
fetchData(handleData);

上記でいうコールバック関数はhandleDataとなる

callback=handleDataという認識でOK

複数回fetchDataを使う場合に上記のような書き方をする。

もし単発使用しかしない場合は、

function fetchData() {
// 模擬的なデータ取得
    setTimeout(() => {
        const data = { name: "John", age: 30 };
        handleData(data); // 直接handleDataを呼び出す
    }, 2000);
}

function handleData(data) {
    console.log("取得したデータ:", data);
}

// fetchData関数を呼び出す
fetchData();` 

って書いてもいい。(この部分理解にめちゃくちゃ時間かかりました、、、。)

引数(ひきすう、Argument)

関数に渡される入力値のことです。関数は、この引数を受け取り、その値を使って特定の処理を行います。

最後に

最後までお付き合いくださりありがとうございました。
自分で書いてみて改めて既存の記事を書かれている方の偉大さが身に沁みました。
少しでもどなたかのお力になれれば幸いです。

次回は残りのフックについても書いていきたいです。
ちょっと今回は単語説明が長すぎるかなと思ったのですが、
全部詰まったところなので、
ご勘弁ください。。。

ありがとうございました!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?