549
658

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Reactを学ぶ上で知っておくべきJavaScriptの基本概念

Last updated at Posted at 2022-10-19

はじめに

今回はFlyCode氏が紹介していた、Reactを学ぶ上で知っておくべきJavaScriptの基本概念を紹介します。

具体的なJavaScriptでのコード解説と、Reactではそれがどのように使われるのかを紹介します。

この記事の対象者

  • JavaScriptのよく使う基本文法を学びたい人
  • Reactの初心者から中級者

この記事の目標

  • React開発でよく使われるJavaScriptの文法や処理を理解する

JavaScriptの基礎文法

本記事では下記の7つをピックアップして紹介します

  • 三項演算子
  • 分割代入
  • スプレッド構文
  • 配列操作
  • アロー関数
  • 非同期処理(Async/Await/Promise)
  • APIコール

三項演算子

三項演算子はMDNでは下記のように解説されています。

条件 (三項) 演算子は JavaScript では唯一の、3 つのオペランドをとる演算子です。

三項演算子の構文

condition ? exprIfTrue : exprIfFalse
  • conditionは値が条件として使用される式
  • exprIfTrueconditiontrueと評価された場合に評価される式
  • exprIfFalseconditionfalseと評価された場合に評価される式

JavaScriptコードで具体例を見ていきます。

  const flag = true;
  const text = flag ? "flagはtrueです" : "flagはfalseです";
  console.log(text);

三項演算子で条件して使用される式( flag)がtrueなのでconsole.logでは「flagはtrueです」が出力されています。
スクリーンショット 2022-10-15 7.58.39.jpg

flagの値をfalseに書き換えると「flagはfalseです」が出力されます。

  const flag = false;
  const text = flag ? "flagはtrueです" : "flagはfalseです";
  console.log(text);

スクリーンショット 2022-10-15 8.00.30.jpg

三項演算子はReact開発ではコンポーネントの出し分けで使われることが多いです。

const Test: React.FC = () => {
  const [isLoading, setIsLoading] = useState<boolean>(true);
  return <>{isLoading ? <Loading /> : <Contents />}</>;
};

上記はisLoadingtrueだった場合は<Loading />が表示され、falseだった場合は<Contents />が表示されます。

今回はisLoadingに初期値としてtrueが入っているので<Loading />が表示されます。

分割代入

分割代入はMDNにおいて

分割代入 (Destructuring assignment) 構文は、配列から値を取り出して、あるいはオブジェクトからプロパティを取り出して別個の変数に代入することを可能にする JavaScript の式です。

と書いてあります。

JavaScriptコードで具体的に見ていきます。

let a,b;
[a,b] = [10,20]
console.log(a)
// 10
console.log(b)
// 20

分割構文はReact開発においてpropsの受け渡しの際に使われることがあります。

【propsを受け取る子コンポーネント】

type ContentsProps = {
  name: string;
  age: number;
};

const Contents: React.FC<ContentsProps> = (props) => {
  // propsを分割代入
  const { name, age } = props;
  return (
    <>
      <p>名前:{name}</p>
      <p>年齢:{age}</p>
    </>
  );
};

【propsの値を受け渡す親コンポーネント】

const Parent: React.FC = () => {
  return <Contents name={"taro"} age={18} />;
};

スクリーンショット 2022-10-15 8.26.09.jpg

スプレッド構文

スプレッド構文はMDNにおいて

スプレッド構文 (...) を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値の組 (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。

と記載されています。

文章だけだとわかりにくいので、具体的なJavaScriptコードを見ていきます。

  const array = [1, 2, 3];
  // コピーの作成
  const copy_array = [...array]; // => [1, 2, 3]
  // 要素を追加し新しい配列を生成
  const new_array = [...array, 4, 5]; // => [1, 2, 3 ,4, 5]
  // 二つの配列をマージする
  const merge_array = [...array, ...new_array]; // => [1 ,2 , 3 , 1, 2, 3 ,4, 5]

スプレッド構文はReact開発においては配列やオブジェクトの`state``更新で使われます。

  const [fruits, setFruits] = useState<string[]>([
    "りんご",
    "みかん",
    "ぶどう",
  ]);

  // イチゴを追加
  const addStrawberry = () => {
    const copy = [...fruits];
    copy.push("いちご");
    setFruits(copy);
  };

  return (
    <>
      {fruits.map((fruit, index) => (
        <p key={index}>{fruit}</p>
      ))}
      <button onClick={addStrawberry}>いちごを追加</button>
    </>
  );

スクリーンショット 2022-10-15 8.46.38.jpg

ボタンをクリックするといちごが増えていることが確認できます。

スクリーンショット 2022-10-15 8.46.59.jpg

また、イチゴを追加する処理においてcopyを取ってる理由は下記の記事で詳しく解説しているので参考にしてみてください。

  // イチゴを追加
  const addStrawberry = () => {
    fruits.push("いちご");
    setFruits(fruits); // => これだとstateが更新されない
  };

配列操作

配列を操作するメソットはmapfilterfindreduceなどがありますが、今回は個人的にReact開発でよく使っている

  • map
  • filter

に絞って解説をしていきます。

map

map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。

【各々の配列の値を2倍にする】

  const array = [1, 2, 3, 4];

  const new_array = array.map((i) => {
    return i * 2;
  });

  console.log(new_array); // => [2,4,6,8]

ReactにおいてmapはJSX内でリストをループする際に使われることが多いです。

  const [fruits, setFruits] = useState<string[]>([
    "りんご",
    "みかん",
    "ぶどう",
  ]);

  return (
    <>
      {fruits.map((fruit, index) => (
        <p key={index}>{fruit}</p>
      ))}
    </>
  );

スクリーンショット 2022-10-15 9.34.12.jpg
他にもAPI等で受け取ったレスポンスデータから必要なデータのみを抽出する場合に使うこともあります。

  // APIコール等のレスポンスデータ
  const responseDate = [
    { id: 1, name: "suzuki", age: 15 },
    { id: 2, name: "satou", age: 20 },
    { id: 3, name: "itou", age: 33 },
  ];

  // レスポンスデータからidとnameのみ抽出
  const result = responseDate.map((i) => {
    return {
      id: i.id,
      name: i.name,
    };
  });

スクリーンショット 2022-10-15 9.38.06.jpg

filter

filterメソットは下記のように解説されています。

filter() メソッドは、この配列の中から、提供された関数で実装されたテストに合格した要素のみを抽出したシャローコピーを作成します。

【wordsの中から6文字より大きいのものだけを抽出】

  const words = [
    "spray",
    "limit",
    "elite",
    "exuberant",
    "destruction",
    "present",
  ];
  const result = words.filter((word) => word.length > 6);

  console.log(result);

filterに関しては検索処理やオブジェクト配列の中から条件に合ったものを抽出するときに利用されます。

【usersの中から管理者権限(admin)を持つuserのみ抽出】

  const users = [
    {
      id: 1,
      name: "tanaka",
      admin: false,
    },
    {
      id: 2,
      name: "takahashi",
      admin: true,
    },
    {
      id: 3,
      name: "matuda",
      admin: false,
    },
    {
      id: 4,
      name: "okamoto",
      admin: true,
    },
  ];

  const admin_users = users.filter((i) => i.admin);

  console.log(admin_users);

スクリーンショット 2022-10-15 10.29.40.jpg

アロー関数

アロー関数はJavaScriptにおいて関数を作成する方法の一つです。

アロー関数の構文は下記のようになっています。

(引数) => {
  // 処理
};

従来の関数をアロー関数に直してみます。

// 従来の関数
function (a, b){
  return a + b + 100;
}
// アロー関数
(a, b) => a + b + 100;

アロー関数を使うメリットについては下記の記事で詳しく解説されているので、ぜひ参考にしてみてください。

非同期処理

非同期処理はMDNでは下記のように解説されています。

非同期プログラミングは、長く続く可能性のあるタスクを開始しても、そのタスクが完了するまで待つのではなく、そのタスクの実行中も他のイベントに応答できるようにする技術です。タスクが完了すると、プログラムはその結果を表示します。

具体例を用いて噛み砕いて解説をします。

【同期処理(コードを書いた順番に処理が実行される)】

  let t = "初期値";
  console.log(t); // => "初期値"と出力
  t = "更新"; 
  console.log(t); // => "更新"と出力

同期処理ではコードを書いた順番で処理が実行されていることが確認できます。

スクリーンショット 2022-10-18 20.59.21.jpg

【非同期処理(コードを書いた順番に処理が実行されない)】

  let t = "0秒";
  console.log(t);
  setTimeout(() => {
    t = "2秒経過しました";
  }, 2000);
  console.log(t);

setTimeout内で2000ミリ秒(2秒)経過する前(処理を待たず)に次のconsole.log(t)の処理が発生しているのでどちらも"0"秒のままになっています。

スクリーンショット 2022-10-18 21.01.26.jpg

このように処理に待ち時間が発生し、かつ処理によって得られる値を利用したい場合、このままだと期待通りの結果を得ることができません。

下記を使うことで上記の処理を行うことができます。

  • Promise
  • async/await

Promise

PromiseはMDNでは下記のように解説されています。

Promise オブジェクトは、非同期処理の完了 (もしくは失敗) の結果およびその結果の値を表します。

具体的にコードで解説をしてきます。

  • new Promiseでインスタンス化する
  • インスタンスの中の引数にコールバック関数を渡す(非同期処理)
  • resolve()が呼ばれた後にthenの中のコールバック処理が呼ばれる
  let t = "0秒";
  console.log(t);
  new Promise((resolve) => {
    setTimeout(() => {
      t = "2秒";
      resolve(t);
    }, 2000);
  }).then((t) => {
    console.log(t);
  });

このようにsetTimeoutの処理を待った後にconsole.log(t)が呼び出されているので期待通りの結果になっていることが確認できます。
スクリーンショット 2022-10-18 21.16.35.jpg

なおPromiseについてのより詳しい解説はこの記事がわかりやすいので、より深堀したいという方は参考にしてみてください。

async/await

async/awaitを利用することでPromiseで書いた処理よりも簡潔に非同期処理を書くことができます。

async/awaitについてはMDNで下記のように解説されています。

非同期関数は async キーワードで宣言され、その中で await キーワードを使うことができます。 async および await キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。

  • Promiseの中のコールバック関数をアロー関数として定義
  • asyncをアロー関数の前に付与
  • awaitを非同期処理の前に付与する
  • 結果として入ってくる値をresultに入れる
  let t = "0秒";
  const timer = async () => {
    const result = await new Promise((resolve) => {
      setTimeout(() => {
        t = "2秒";
        resolve(t);
      }, 2000);
    });
    console.log(result);
  };
  timer();

これによってthenを書かずに先ほどと同じ処理が行われていることが確認できます。

スクリーンショット 2022-10-18 21.47.02.jpg

async/awaitについてより詳しく知りたい人は下記の記事を参考にしてみてください。

APIコール

最後にJavaScriptの開発で必須項目でもあるAPI通信について解説をします。

クライアントとサーバー間のデータ通信について

まずクライアントサイドとサーバーサイドの通信について簡単に解説します。

  1. クライアント(JavaScript等)からほしい情報をサーバーにリクエスト
  2. サーバー(RubyやPHP等)はリクエストを受けデータをレスポンス
  3. レスポンス(HTMLやJSON形式等)をクライアント側(画面)で表示

ネタ系.001.jpeg

REST API

REST APIはリソースごとにURLのパスが準備されています。

リクエスト送信時のメソット(GET,POST,PUT,DLETE)を変えて同じリソースにリクエストを行うことで処理が実行されます。

ネタ系1.001.jpeg

今回は先ほど紹介した下記の部分においてデータを実際に取得する処理を書いてきます。
ネタ系12.001.jpeg

axiosを使ってAPIコール

APIコールをするためにJavaScriptではaxiosというライブラリが用意されています。

axiosを使うことで、GETやPOSTのHTTPリクエストを使ってサーバーからデータの取得、サーバーへデータ送信、追加、更新、削除を行うことができます。

JSONPlaceholderを使って具体的にデータを取得する処理を書いてみます。

【JSONPlaceholderからusers情報をGETするリクエストを送る】

 const getUsers = async () => {
    const res = await axios.get("https://jsonplaceholder.typicode.com/users");
    console.log(res.data);
  };
  getUsers();

APIコールは外部との通信が走るので先ほど紹介した非同期処理のasync/awaitを利用しています。

下記のようにusers情報が返ってきていることが確認できます。
スクリーンショット 2022-10-19 9.34.16.jpg

またReactにおけるAPIコールは副作用なのでuseEffect内で呼び出されることが多いです。(useAsync等もある)

  const [user, setUsers] = useState<User>([]);
  useEffect(() => {
    const getUsers = async () => {
      const res = await axios.get("https://jsonplaceholder.typicode.com/users");
      setUsers(res.data);
    };
    getUsers();
  }, []);

  console.log(user);

スクリーンショット 2022-10-19 9.53.21.jpg

なぜuseEffectの中で呼び出されるかについての詳しい解説は下記の記事でおこなっているので参考にしてみてください。

最後に

いかがだったでしょうか。

今回はReactを学ぶ上で知っておくべきJavaScriptの基本概念についてまとめました。

他にもReact関連の記事を出しているので、合わせて読んでいただけると嬉しいです。

549
658
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
549
658

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?