【React】Reactでよく使うJavaScriptの記法２

#### はじめに
Reactでよく使われるJavaScriptの記法についてまとめました。（前回の続きです。）

主に参考にしたのは以下の講座です。
[【2023年最新】React(v18)完全入門ガイド｜Hooks、Next.js、Redux、TypeScript](https://www.udemy.com/course/react-complete-guide/)


## e.preventDefault()

参考資料
[【JavaScript】event.preventDefault()が何をするのか - Qiita](https://qiita.com/yokoto/items/27c56ebc4b818167ef9e)

submitイベントの発生元であるフォームが持つデフォルトの動作をキャンセルするメソッド

フォームが持つデフォルトの動作
：フォームの内容を指定したURLへ送信するという動作

※actionのところを省略すると、現在開いているページにリクエストを送信して、再度そのページでリロードされる

## 分割代入

参考資料
[【初学者向け】JavaScriptの分割代入について - Qiita](https://qiita.com/yasu-hoshi/items/cf33f50fdec26537842a)

配列やオブジェクトから値を取り出して、変数に代入してくれるJavaScriptの機能	
	
通常の代入では一つの変数に対して一つの値を代入していくのに対して、分割代入は複数の変数に、配列やオブジェクトの値を一度に設定する

#### ①配列の場合	
左辺の変数は [ ] で囲う

```javascript
const arry = [10, 20, 30];
//分割代入
const [a, b, c] = arry;

//確認
console.log(a);  // 10
console.log(b);  // 20
console.log(c);  // 30
```

#### ②オブジェクトの場合	
左辺の変数は { } で囲う
変数名とプロパティは一致させる必要がある

```javascript
//オブジェクトを作成
const obj = {
    name: "Tom",
    age: 87
   }

//分割代入
const {name, age} = obj;

//確認
console.log(name);  //Tom
console.log(age);   //87
```

## スプレッド構文(Spread Syntax)

参考資料
[JSのスプレッド構文を理解する - Qiita](https://qiita.com/akisx/items/682a4283c13fe336c547)

...XXXの形で記述され、配列やオブジェクトの要素を文字通り展開する構文。
Array.prototype.concat()相当のことが簡潔にかける。

#### ①配列の場合
```javascript
const foo = [1, 2];

// 配列のクローン
const bar = [...foo]; // => [1, 2]

// 要素を追加して新しい配列を生成
const baz = [...foo, 3, 4]; // => [1, 2, 3, 4]

// 配列をマージ
const hoge = [...foo, ...bar]; // => [1, 2, 1, 2]
```

#### ②オブジェクトの場合
```javascript
const foo = { a: 1, b: 2 };

// オブジェクトのクローン
const bar = { ...foo }; // => { a: 1, b: 2 }

// プロパティを追加した新しいオブジェクトの生成
const baz = { ...foo, c: 3 }; // => { a: 1, b: 2, c: 3 }

// オブジェクトのマージ
const hoge = { ...foo, ...{ c: 3, d: 4 } }; // => { a: 1, b: 2, c: 3, d: 4 }

// 元のオブジェクトに同名プロパティがある場合は置き換わる
const fuga = { ...foo, b: 3 }; // => { a: 1, b: 3 }
const piyo = { ...foo, ...{ a: 3, b: 4 } }; // => { a: 3, b: 4 }
```

## 残余引数

参考資料
[スプレッド構文と残余引数について【備忘録】 #JavaScript - Qiita](https://qiita.com/azu_nyan/items/6735c1cf08e8f650bda7)

実行時に渡される引数の数がわからない場合に、
実際に引数として渡された複数の値を配列としてまとめて「残余引数」に格納することができる

```javascript
function sample2(firstItem, ...restItem) { 
    console.log(firstItem);
    console.log(restItem);
}

sample2('緑茶', '抹茶', 'チャイ', 'ココア');
/* 実行結果
緑茶
['抹茶', 'チャイ', 'ココア']
```

## 三項演算子

参考資料
[【初学者向け】JavaScriptの三項演算子『?』について #JavaScript - Qiita](https://qiita.com/yasu-hoshi/items/2f88e725ea81ac402bd2)

+ if文の場合

```javascript
if (条件式) {
trueの場合の処理
} else {
falseの場合の処理
}
```

条件式が
trueなら→trueの場合の処理を実行
falseなら→falseの場合の処理を実行

+ 三項演算子の場合

```javascript
条件式 ? trueの場合の処理 : falseの場合の処理;
```

条件式の後に「？」を記述
→trueなら直後のtrueの場合の処理を実行
→falseなら「:」の後のfalseの場合の処理を実行

## Null合体演算子

参考資料
[【JavaScript】Null合体演算子と(??)とオプショナルチェイニング演算子(?.) - Qiita](https://qiita.com/azukiazusa/items/b91046e9f1d618c67d7f)

```javascript
A ?? B
```

演算子の一種で左辺がnullまたはundefinedのときに右辺の値を返し、それ以外のときには左辺を返す。

## falsyな値とtruthyな値

参考資料
[[ JavaScript入門 ] falsyな値とtruthyな値とはなんなのか？またどのような時に使用するのか。 - Qiita](https://qiita.com/Zone_1997/items/225851ccdb921f253793)

+ falsyな値				
Booleanで真偽値に変換した場合にfalseになる値のこと。			(例:false,null,0,undefined.0n,NaN)

+ truthyな値				
falsyな値以外			

## Promise

参考資料
[【JavaScript】 非同期はPromise？解説が難しいので自分で理解してみた (affi-sapo-sv.com)](https://note.affi-sapo-sv.com/js-promise.php)
[【ES6】 JavaScript初心者でもわかるPromise講座 - Qiita](https://qiita.com/cheez921/items/41b744e4e002b966391a)
[PromiseとAsync/Awaitについて - Qiita](https://qiita.com/ta1m1kam/items/d60ab1ecdcb6aef82eca)
[JavaScriptのPromiseを理解する - Qiita](https://qiita.com/cotton11aq/items/e4719a7deacb7663a0b8)

処理の順序（処理を待機することや、その結果に応じて次の処理をすること）を約束するもの

PromiseStatusという3つの状態がある

・pending: 未解決 (処理が終わるのを待っている状態)
・resolved: 解決済み (処理が終わり、無事成功した状態)
・rejected: 拒否 (処理が失敗に終わってしまった状態)

＜基本的な書き方＞

```javascript
new Promise((resolve,reject) => {
  // 同期処理
  resolve() // もしくは reject()
})
  .then(() => {
    // 非同期処理(resolveを待つ)
  })
  .catch(() => {
    // 非同期処理(rejectを待つ)
  })
  .finally(() => {
    // 非同期処理(then、またはcatchを待つ)
  });
```

new Promiseの引数に与えたコールバック関数は同期処理される。	
thenメソッドやcatchメソッド、finallyメソッドは全て非同期で実行される。	
	
resolveが呼ばれた場合は、thenメソッドの中のコールバック関数が実行され、このコールバック関数の引数にはresolveで渡した実引数が渡る。	
thenメソッドが完了すると、catchメソッドはスキップされ、finallyメソッドに処理が移る。	

```react
const Test = () => {
  console.log("1番目");

  // 約束を取り付けたい処理にPromiseを使う
  new Promise((resolve) => {
    //1秒後に実行する処理
    setTimeout(() => {
      console.log("2番目(1秒後に実行)");
      //無事処理が終わったことを伝える
      resolve();
    }, 1000);
  }).then(() => {
    // 処理が無事終わったことを受けとって実行される処理
    console.log("3番目");
  });
  return (
    <p>テスト</p>
  )
};
function App2() {
  return (
    <>
      <Test />
    </>
  );
}

```

実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/546adc97-c836-2fb4-6b37-214bbe383d82.png" width="200">



#### resolve関数
戻り値：Promiseオブジェクトを返す

この戻り値を次に呼ばれるメソッド(then)の第一引数に渡すことが出来る。

```react
const promise = new Promise((resolve) => {
    // 引数に文字列を渡す
    resolve("resolveしたよ");
  }).then((val) => {
    // 第一引数にて、resolve関数で渡した文字列を受け取ることができる
    console.log(val);
  });
```
実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/2f96ef24-96d9-a051-ad95-570ab13ab4ae.png" width="150">

## Promise.all

配列でPromiseオブジェクトを渡し、全てのPromiseオブジェクトがresolvedになったら次の処理に進む。

```react
Promise.all([非同期処理1, 非同期処理2, ...])
  .then((result) => {
    // 全ての非同期処理が成功した
  })
  .catch((result) => {
    // いづれかの非同期処理が失敗した
  });
```

```react
const Test = () => {
  const promise1 = new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 1000);
  }).then(() => {
    console.log("promise1おわったよ！");
    return ("promise1戻り値");
  });

  const promise2 = new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 3000);
  }).then(() => {
    console.log("promise2おわったよ！");
    return ("promise2戻り値");
  });

  Promise.all([promise1, promise2])
    .then((val) => {
      console.log("引数val :" + val);
      console.log("全部おわったよ！");
    });
  return (
    <p>テスト</p>
  )
};

function AppTest() {
  return (
    <>
      <Test />
    </>
  );
}
export default AppTest;
```

実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/6d3763cd-ab4b-27cc-4fea-4330316d1381.png" width="250">

#### new PromiseとPromise.resolveの違い

参考資料
[new PromiseとPromise.resolveの違い - Qiita](https://qiita.com/ueokande/items/807a6c9a64c3874a0f83)

＜正常処理の場合＞

```react
    function fn() {
        return 'Hello';
    }

    var ret1 = new Promise(function (resolve) {
        resolve(fn());
    });
    console.log(ret1);

    var ret2 = Promise.resolve(fn());
    console.log(ret2);
```

実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/12555d15-882a-7490-42cc-622f612f7359.png" width="250">

実行結果はどちらも 'Hello' でresolveされた Promise オブジェクトが返って来る。

＜例外が発生する場合＞
```react
    function fn() {
        //例外を発生させる
        throw new Error('BAAD');
    }

    var ret1 = new Promise(function (resolve) {
        resolve(fn());
    });
    // 例外発生時はrejectされた Promise オブジェクトが返される
    console.log(ret1);

    var ret2 = Promise.resolve(fn());
    console.log(ret2);
```

実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579718/de0488dd-2694-0513-c119-1850f491ad81.png" width="250">

new Promiseだと、コンストラクタ内で渡された関数を try{} で例外処理して呼び出し、
例外発生時はrejectされた Promise オブジェクトを返す。

Promise.resolveだと、 Promise.resolveの呼び出し前に例外がトップレベルで発生し、プログラムが終了する。

そのためret1の結果のみ返ってくる。

#### setTimeout

参考資料
[awaitできるsetTimeoutを1行で書く方法 - Qiita](https://qiita.com/suin/items/99aa8641d06b5f819656)

☆以下のように省略して記載できる。
例）3000ミリ秒待機するという処理。すべて同じ実行結果となる。

＜基本的な長めの書き方＞
```react
const sleep = () => new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, 3000)
  })
  await sleep()
```

＜省略系＞
```react
// 1: () => { resolve() } は resolve に短縮する
const sleep = () => new Promise(resolve => {
    setTimeout(resolve, 3000)
})
await sleep()

// 2: resolve => {} は resolve => に短縮する
const sleep = () => new Promise(resolve => setTimeout(resolve, 3000))
const promise = sleep()
await promise

// 3: sleep()は関数でなくていいので値にする
const promise = new Promise(resolve => setTimeout(resolve, 3000))
await promise

// 4: 完成
await new Promise(resolve => setTimeout(resolve, 3000))
```