【初心者向け】Reactでよく使うJavaScriptのメソッドや構文13選とReact Hooks(プチ紹介)

# はじめに
最近、ひょんなことから初学者向けのReactアプリをレベル別に10個くらい開発しながら、ハンズオンで学べる教材的なものを作成する機会があり、それを実施する前に最低限理解していたら学習がスムーズに進むだろうと思われるものをまとめました。

また、予習編としてReact専用で使用されるものも簡単に紹介します。

ちなみに、すでに「基本編くらいわかるわ！」って方は予習編はみなくていいので、以下の[リファレンスのチュートリアル](https://ja.react.dev/)をやっちゃってください。Udemyなんかでもいいと思いますのでどんどん手を動かすフェーズに入っていきましょう。

https://ja.react.dev/
![スクリーンショット 2024-05-27 7.46.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492127/764e3325-b21f-c076-583a-d44d00ac5847.png)


また、JavaScriptは全くわからんという方は、こちらの実際にアニメーションや動くものを作りながら学べる教材を作成しましたので、是非、使ってください。もちろん無料です:point_up:

https://qiita.com/Dragon1208/items/92b2618eb1135f375553

# 基本編(JavaScript)
1. **`map`メソッド**
   - 配列内の全ての要素に対して関数を適用し、新しい配列を作成します。
   ```javascript
   const items = ['apple', 'banana', 'cherry'];
   const listItems = items.map(item => <li key={item}>{item}</li>);
   ```
   - `items`配列の各要素を`<li>`タグで囲み、`listItems`という新しい配列を作成します。
   - 特にこのmap()はアホみたいにReactでは出現しますので、もう覚えちゃいましょう。一番出てくるのは以下のような形です。

    ```react
    const todos = [
      { id: 1, text: 'Learn JavaScript', completed: false },
      { id: 2, text: 'Build a Todo App', completed: false },
      { id: 3, text: 'Master React', completed: false }
    ];
    
    function TodoList() {
      return (
        <ul className=''> // スタイリングは省略
          {todos.map((todo) => (
            <li key={todo.id}>
              {todo.text}
            </li>
          ))}
        </ul>
      );
    }
    
    export default TodoList;
    
    ```
<br/>

2. **`filter`メソッド**
   - 配列内の要素をフィルタリングして、新しい配列を作成します。
   - こちらもよく使用されます。map()と形が似ていて初学者の方は混乱するかもしれませんが違いを理解しておきましょう。
   ```javascript
   const numbers = [1, 2, 3, 4, 5];
   const evenNumbers = numbers.filter(number => number % 2 === 0);
   ```
   - `numbers`配列から偶数だけを含む新しい配列`evenNumbers`を作成します。
   
   例えばTodoなんかの削除機能がわかりやすい例かと思います。以下のように、**対象のtodoのidと一致しないid**をフィルタリングしてあげれば**引数で渡されたidのtodoは除外された配列**が作成されて、delete機能が完成します。
   ```typescript
   const [todo, setTodo] = useState<{ text: string; isComplete: boolean }[]>([]);
   // 省略
   const deleteTodo = (index: number) => {
    setTodo((prev) => prev.filter((_, i) => i !== index));
   };
   ```
   <br/>

3. **スプレッド構文**
   - 配列やオブジェクトを展開してコピーを作成します。
   ```javascript
   const obj1 = { a: 1, b: 2 };
   const obj2 = { ...obj1, c: 3 };
   ```
   - `obj1`の全てのプロパティをコピーし、さらに`c: 3`を追加した新しいオブジェクト`obj2`を作成します。
   <br/>

4. **分割代入**
   - オブジェクトや配列から特定のプロパティや要素を抽出して変数に代入します。
   ```javascript
   const user = { name: 'John', age: 30 };
   const { name, age } = user;
   ```
   - `user`オブジェクトから`name`と`age`を取り出して、それぞれ変数`name`と`age`に代入します。
   <br/>

5. **アロー関数**
   - 簡潔な関数定義の方法です。
   ```javascript
   const add = (a, b) => a + b;
   ```
   - `a`と`b`を引数として受け取り、それらの和を返す関数`add`を定義します。
   <br/>


6. **テンプレートリテラル**
   - 文字列を簡単に組み立てる方法です。
   ```javascript
   const name = 'John';
   const greeting = `Hello, ${name}!`;
   ```
   - 文字列内に変数`name`の値を埋め込んで、`Hello, John!`という文字列を作成します。
   <br/>

7. **オプショナルチェイニング**
   - 存在しないプロパティにアクセスしてもエラーにならないようにする構文です。
   ```javascript
   const user = { address: { city: 'Tokyo' } };
   const city = user?.address?.city;
   ```
   - `user`オブジェクトの`address`プロパティが存在する場合に`city`にアクセスします。
   <br/>

8. **Null合体演算子**
    - 左側の値が`null`または`undefined`の場合に右側の値を返します。
    ```javascript
    const name = user.name ?? 'Guest';
    ```
    - `user.name`が`null`または`undefined`の場合、`'Guest'`を返します。
    <br/>

9. **`find`メソッド**
    - 配列内の条件に一致する最初の要素を返します。
    ```javascript
    const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
    const user = users.find(user => user.id === 1);
    ```
    - `users`配列から`id`が1の最初のユーザーを見つけます。
    <br/>

10. **`reduce`メソッド**
    - 配列を一つの値にまとめます。
    ```javascript
    const numbers = [1, 2, 3, 4];
    const sum = numbers.reduce((total, number) => total + number, 0);
    ```
    - `numbers`配列の全ての要素を合計して`sum`を計算します。
    <br/>

11. **プロパティショートハンド**
    - オブジェクトリテラルの簡潔な記述方法です。
    ```javascript
    const name = 'Alice';
    const age = 30;
    
    const person = {
      name: name, // この左辺と右辺が同じ場合は省略可能
      age: age
    };

    console.log(person); // { name: 'Alice', age: 30 }

    // 省略した形
    const name = 'Alice';
    const age = 30;
    
    const person = {
      name,
      age
    };

    console.log(person); // { name: 'Alice', age: 30 }

    ```
    - `name`と`age`をそのままオブジェクトのプロパティとして使用します。
    <br/>

12. **論理AND (&&) 演算子**
    - 条件が真の場合にのみ要素を表示します。
    ```React
    const isLoggedIn = true;
    return (
      <div>
        {isLoggedIn && <button>Logout</button>}
      </div>
    );
    ```
    - `isLoggedIn`が`true`の場合にのみ`<button>Logout</button>`を表示します。
    <br/>

13. **条件付きレンダリング（三項演算子）**
    - 条件によって表示内容を切り替えます。
    ```React
    const isLoggedIn = true;
    return (
      <div>
        {isLoggedIn ? <button>Logout</button> : <button>Login</button>}
      </div>
    );
    ```
    - `isLoggedIn`が`true`の場合は`<button>Logout</button>`を表示し、`false`の場合は`<button>Login</button>`を表示します。
    
また、以下のように動的にスタイリングするためにもよく使用されます。

**ボタンの有効/無効状態のスタイリング**
```react
import { useState } from 'react';
import { Button } from '@chakra-ui/react';

const DynamicButton = () => {
  const [isDisabled, setIsDisabled] = useState(true);

  return (
    <Button
      onClick={() => setIsDisabled(!isDisabled)}
      bg={isDisabled ? 'gray.400' : 'blue.500'}
      color={isDisabled ? 'white' : 'black'}
      cursor={isDisabled ? 'not-allowed' : 'pointer'}
      disabled={isDisabled}
    >
      {isDisabled ? 'Disabled' : 'Enabled'}
    </Button>
  );
};

export default DynamicButton;

```

**アラートメッセージの種類に基づくスタイリング**

```react
import { Box } from '@chakra-ui/react';

const AlertMessage = ({ type, message }) => {
  return (
    <Box
      p={4}
      bg={
        type === 'success'
          ? 'green.200'
          : type === 'error'
          ? 'red.200'
          : 'gray.200'
      }
      color={
        type === 'success'
          ? 'green.800'
          : type === 'error'
          ? 'red.800'
          : 'gray.800'
      }
    >
      {message}
    </Box>
  );
};

export default AlertMessage;

```


- 条件Aならこのスタイルをあてる、そうでなければBのスタイルをあてるといった具合です。

<br>

### さらに詳しく知りたい方はこちらをどうぞ
https://qiita.com/Dragon1208/items/7458eddb179b8f225e37

# 破壊的メソッドと非破壊的メソッドを理解する
JavaScriptにおけるよく使用されるメソッドを、破壊的メソッドと非破壊的メソッドに分類します。なあなあにしがちですが、**かなり重要な部分**なので簡単に記載しておきます。

詳しくはこちらに記載しましたのでご覧ください:writing_hand:

https://qiita.com/Dragon1208/items/4b4568bb61b0ca3aef3c

### 破壊的メソッド (Destructive Methods)
破壊的メソッドは、元の配列やオブジェクトを直接変更するメソッドです。

#### 配列の破壊的メソッド
1. `push()`: 配列の末尾に1つ以上の要素を追加します。
2. `pop()`: 配列の末尾の要素を削除します。
3. `shift()`: 配列の先頭の要素を削除します。
4. `unshift()`: 配列の先頭に1つ以上の要素を追加します。
5. `splice()`: 配列の指定された部分に要素を追加、削除、または置換します。
6. `sort()`: 配列をソートします。
7. `reverse()`: 配列の要素を反転させます。
8. `fill()`: 配列の要素を指定した値で埋めます。

#### オブジェクトの破壊的メソッド
1. `Object.assign()`: オブジェクトのプロパティを別のオブジェクトにコピーするためのメソッドです。複数のソースオブジェクトからターゲットオブジェクトにプロパティをコピーすることができます。
    ```javascript
    const target = { a: 1, b: 2 };
    const source = { b: 4, c: 5 };
    
    const returnedTarget = Object.assign(target, source);
    
    console.log(target); // { a: 1, b: 4, c: 5 }
    console.log(returnedTarget); // { a: 1, b: 4, c: 5 }
    
    ```
    <br/>
2. `Object.freeze()`: オブジェクトを凍結し、そのプロパティを変更できないようにするためのメソッドです。凍結されたオブジェクトは、プロパティの追加、削除、変更ができなくなります。
    ※元オブジェクトの中身は変わりませんが、状態が変わってしまう（追加、削除などができなくなる）ので破壊的とみなされます。
    ```javascript
    const obj = {
      prop: 42
    };
    
    Object.freeze(obj);
    
    obj.prop = 33; // この変更は無視されます
    obj.newProp = 'new'; // この追加も無視されます
    delete obj.prop; // この削除も無視されます
    
    console.log(obj.prop); // 42
    console.log(obj.newProp); // undefined
    ```
    <br/>
3. `Object.seal()`: オブジェクトをシール(封印)し、既存のプロパティを変更可能に保ちながら、新しいプロパティの追加や既存プロパティの削除を禁止するメソッドです。これにより、オブジェクトの形状が固定され、追加や削除による変更が防止されますが、プロパティの値は変更できます。
    ```javascript
    const obj = {
      prop: 42
    };
    
    Object.seal(obj);
    
    obj.prop = 33; // プロパティの値は変更可能
    obj.newProp = 'new'; // 新しいプロパティの追加は無視される
    delete obj.prop; // プロパティの削除は無視される
    
    console.log(obj.prop); // 33
    console.log(obj.newProp); // undefined

    ```

#### 破壊的な演算子
1. `delete`: オブジェクトからプロパティを削除します。

### 非破壊的メソッド (Non-Destructive Methods)
非破壊的メソッドは、元の配列やオブジェクトを変更せず、新しい配列やオブジェクトを返すメソッドです。

#### 配列の非破壊的メソッド
1. `concat()`: 2つ以上の配列を結合します。
2. `slice()`: 配列の一部を新しい配列として抽出します。
3. `map()`: 配列の各要素に対して関数を適用し、新しい配列を返します。
4. `filter()`: 条件を満たす要素を含む新しい配列を返します。
5. `reduce()`: 配列を1つの値にまとめます。
6. `reduceRight()`: 配列を右から左に1つの値にまとめます。
7. `find()`: 条件を満たす最初の要素を返します。
8. `findIndex()`: 条件を満たす最初の要素のインデックスを返します。
9. `some()`: 少なくとも1つの要素が条件を満たすかをチェックします。
10. `every()`: 全ての要素が条件を満たすかをチェックします。
11. `includes()`: 配列が特定の要素を含むかをチェックします。
12. `indexOf()`: 配列内の特定の要素の最初のインデックスを返します。
13. `lastIndexOf()`: 配列内の特定の要素の最後のインデックスを返します.
14. `join()`: 配列の全要素を文字列として結合します.

#### オブジェクトの非破壊的メソッド
2. `Object.keys()`: オブジェクトのキーの配列を返します。
3. `Object.values()`: オブジェクトの値の配列を返します。
4. `Object.entries()`: オブジェクトのキーと値のペアの配列を返します。




# 予習編（React専用のHooksとTailwind CSS）
ちなみによくHook(フック)という言葉が用いられるのですが、これは**特定のイベントやライフサイクルのタイミングで追加の処理を挿入するための仕組み**のことです。

React初学者の方はここからは「こんなものがあるんだなぁ」くらいでいいと思います。
解説を最低限にしてますので、余裕があれば各Hooksを調べてみましょう。


1. **`useState`フック**
   - コンポーネント内で状態を管理するためのフックです。
   ```javascript
   const [count, setCount] = useState(0);
   ```
   - `count`という状態変数を宣言し、初期値を0に設定します。`setCount`は`count`を更新するための関数です。
   <br/>


2. **`useEffect`フック**
   - 副作用（データのフェッチやDOMの操作など）を実行するためのフックです。
   ```javascript
   useEffect(() => {
     // コンポーネントがマウントされた時の処理
     return () => {
       // クリーンアップ処理
     };
   }, []);
   ```
   - 第二引数を使用して(ここでは[]のこと)、コンポーネントが初めて表示された時や特定の値が変化した時に実行される処理を記述します。
   <br/>


3. **`useRef`フック**
    - DOM要素や値を保持するためのフックです。
    ```javascript
    const inputRef = useRef(null);
    useEffect(() => {
      inputRef.current.focus();
    }, []);
    ```
    - `inputRef`を使って入力フィールドを参照し、コンポーネントが表示された時にフォーカスを当てます。

例えば、textareaに対してuseRefを使用して、入力された値を取得したりできます。
```javascript
const SimpleTodo: NextPage = () => {
    // 省略
    const textAreaRef = useRef<HTMLTextAreaElement>(null);
    
    return (
        <textarea
            ref={textAreaRef}
            placeholder="useRefを使用したTodoアプリ" />
     )
 }
```
```javascript
// 取得方法
const textAreaValue = textAreaRef.current?.value;
```

### useRefについての詳細を知りたい方はこちらからどうぞ:point_down:
https://qiita.com/Dragon1208/items/320bf04672050c4dcaeb

<br/>

4.**`useContext`フック**
- Reactアプリケーション全体でデータをグローバルに共有するためフックです。
    ```javascript
    const MyContext = CreateContext();
    const value = useContext(MyContext);
    ```
    - `MyContext`から値を取得します。
    <br/>

5.**`useMemo`フック**
- レンダー間で計算結果をキャッシュ(メモ化)するためのフックです。
    ```javascript
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    ```
    - `a`と`b`が変わらない限り、`computeExpensiveValue`の結果を再計算せずに返します。
    <br/>

6.**`useCallback`フック**
- 関数をメモ化するためのフックです。
    ```javascript
    const memoizedCallback = useCallback(() => {
      doSomething(a, b);
    }, [a, b]);
    ```
    - `a`と`b`が変わらない限り、同じ関数インスタンスを返します。
    <br/>

7.**`useState` `useEffect`使用したfetch API**
- ネットワークリクエストを送信してデータを取得するためのAPIです。
    ```javascript
    const DataFetchingComponent = () => {
  const [data, setData] = useState(null); // useState フックを使用して state を定義

  useEffect(() => {
        fetch('https://api.example.com/data')
          .then(response => response.json())
          .then(data => setData(data)); // 取得したデータを state にセット
      }, []); // 空の依存配列により、コンポーネントの初回マウント時のみ実行
      
      return (
              // 省略
          );
      }
    ```
    - APIからデータを取得して`setData`で状態を更新します。

## 注意点
「`useEffect`, `useMemo`, `useCallback`の第2引数が変化しない＝実行されない」ではないのでご注意ください。

例えばコンポーネントの状態が変わったり、親コンポーネントが再レンダリングされたりすると、Reactのスケジューリングの関係で依存配列が変わっていなくても再実行される場合があります。他にも要因はありますが頭の片隅に入れておきましょう。

# **Tailwind CSS**を使用したスタイリング
Reactでの開発で大活躍するのはこの**Tailwind CSS**です。
簡単に言うとHTMLタグ内に直接、しかも短縮した形で記述していく形になります。
単純なスタイリングだけでも効率が良くなるのですが、その他にもアニメーションや動的なスタイリング、動的なレスポンシブ対応など可能性は無限大です。

以下のドキュメントは必ず目を通しておきましょう

https://tailwindcss.com/


**Tailwind CSSの能力を爆上げする小技集 Best 3**

https://qiita.com/Dragon1208/items/0e129e8561492ad5945b

# おススメの書籍
最近はリスキリングサービスの発展で動画学習が主体になっていますが、手元に一冊あると重宝する位置づけのものを紹介します。

**独習JavaScript**
https://amzn.to/3KkBWEG

この書籍のいいところは、**「初心者はスキップしていいところ」「レベルアップしたい人用」** などが項目に記載してあって、さらにJSのメカニズム的な部分から丁寧に説明されてあるので、辞書的な使い方でもいいですし、ゆっくりわからないところはGPTに聞きながら独習するという感じでもかなり勉強になります。

# 【補足】たまに使うメソッドを紹介する(初心者スルーしてOK)

## `flatMap()` 
   `flatMap()`は配列内の各要素に対して指定された関数を適用し、その結果をフラットな配列として結合します。これは`map()`と`flat()`を一度に行うような動作をします。

### 基本的な使い方

```javascript
const array = [1, 2, 3, 4];
const result = array.flatMap(x => [x, x * 2]);
console.log(result); // [1, 2, 2, 4, 3, 6, 4, 8]
```

この例では、元の配列の各要素に対して、要素自身とその2倍の値を持つ配列を返し、その結果をフラットな配列として結合しています。

#### 使い方の例

1. **ネストされた配列のフラット化**:
   `flatMap()`は、ネストされた配列を1段階フラットにするのに便利です。

   ```javascript
   const nestedArray = [[1], [2], [3], [4]];
   const flatArray = nestedArray.flatMap(x => x);
   console.log(flatArray); // [1, 2, 3, 4]
   ```
   <br/>

2. **フィルタリングとマッピングの組み合わせ**:
   `flatMap()`を使うと、フィルタリングとマッピングを一度に行うことができます。

   ```javascript
   const numbers = [1, 2, 3, 4, 5];
   const evenSquares = numbers.flatMap(x => x % 2 === 0 ? [x * x] : []);
   console.log(evenSquares); // [4, 16]
   ```
   この例では、偶数の要素だけを2乗して返し、フラットな配列にしています。
   <br/>

3. **複雑な変換**:
   `flatMap()`を使って、各要素をより複雑な構造に変換することもできます。

   ```javascript
   const sentences = ["this is a sentence", "another sentence"];
   const words = sentences.flatMap(sentence => sentence.split(" "));
   console.log(words); // ["this", "is", "a", "sentence", "another", "sentence"]
   ```

   この例では、文を単語に分割し、すべての単語を一つのフラットな配列にしています。


### 参考資料

- [MDN Web Docs - Array.prototype.flatMap()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap)
- [JavaScript.info - Array methods: flatMap](https://javascript.info/array-methods#flatmap)
<br/>

# 終わりに
全て覚える必要はありませんが、それぞれの特徴を理解してどういう動きをするかだけは押さえておきましょう。
特に破壊的メソッドと非破壊的メソッドに関しては、「元のオブジェクトそのものの状態や性質を変更してしまう」ものとそうでないものがあるという認識で頭に入れておけばいいと思います。

それぞれの理解ができたらGPT先生に聞いて、実際にそのメソッドや構文を利用した実用例を出してもらって理解を深めるとさらにいいと思います。