【初心者用】Reactの基本【備忘録】

# これは何？
Reactを初めて触ったので、すぐに思い出せるように、基本をまとめた記事です。

# 目次
[目次](#目次)
[Reactの環境構築](#reactの環境構築)
[書き始める前のお決まりのお作法](#書き始める前のお決まりのお作法)
[JSX記法](#jsx記法)
[コンポーネント](#コンポーネント)
[イベントとstyle](#イベントとstyle)
[props](#props)
[state](#state)
[useEffect](#useEffect)
[通常のexportとdefault export](#通常のexportとdefault-export)
[終わりに](#終わりに)

# Reactの環境構築
0から環境構築をするのは大変なので、Create React Appを使用する

1. Node.jsをインストールする
1. 下記のコマンドを入力する
```
npx create-react-app my-app
cd my-app
npm start
```
1. 自動的にブラウザにReactの文字が表示される
1. srcディレクトリ配下のファイルをすべて削除し、新しくindex.jsを作成する
1. index.jsを編集していく



# 書き始める前のお決まりのお作法
1. index.htmlに下記が書かれていることを確認
```html
<div id="root"></div>
```
1. index.jsに下記を追加
```js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
```

1. App.jsを新しく作成し、App.jsに下記を記述する
```react
import React from 'react';

// ここにReactを記述する

export default App;
```

1. App.jsにReactを記述していく

:::note info
Reactの拡張子はjsxだが、jsでも問題ない。もちろんjsxにしても良い
:::





# JSX記法
JavaScript の構文の拡張で、htmlタグを式の中に記述する書き方。

```react
const App = () => {
    return (
        <>
            <h1>こんにちは</h1>
            <p>お元気ですか？<p>
        </>
    );
};
```
:::note info
複数のタグを記述する場合、`<>`か`<React.fragment>`で囲む必要がある
:::




# コンポーネント
UI を独立した再利用できる部品に分割し、部品それぞれを分離して考えることができるようになる。
すでにApp.jsxを作成しているが、それがコンポーネント。
関数コンポーネントとクラスコンポーネントがあるが、基本的に関数コンポーネントだけでOK。

:::note warn
コンポーネントのファイル名は必ずパスカルケースで記述すること
:::



# イベントとstyle
## イベント
htmlタグの中で扱うイベントやstyleの名称はすべてキャメルケースになる。
また、波括弧で囲むことでjavaScriptを記述することができる。
```react
const App = () => {
    const onClickButton = () => alert();
    return (
        <button onClick={onClickButton}>ボタン</button>
    );
};
```
:::note info
javaScriptのonclickイベントがonClickとして記述されている
波括弧内にjavaSciptで定義した変数を渡すことができる
:::

## style
htmlタグに直接styleを記述することができる
```react
const App = () => {
    return (
        <h1 style={{ color: 'red' }}>こんにちは</h1>
    );
};
```
:::note info
外側の波括弧はjavaScirptとして記述しますよ、という波括弧
内側の波括弧はjavaScriptのオブジェクトとしての波括弧
:::

変数を渡すこともできる
```react
const App = () => {
    const contentStyle = {
        color: 'red',
    };
    return (
        <h1 style={contentStyle}>こんにちは</h1>
    );
};
```




# props
コンポーネントに渡す引数のようなもの。
```react
// App.jsxに記述
const App = () => {
    return (
        <>
            <ColorfulMessage color='blue' message='How are you?'/>
            <ColorfulMessage color='green' message='Good!'/>
        </>
    );
};
```
```react
// ColofulMessage.jsxに記述
import React from 'react';

const ColorfulMessage = (props) => {
    const contentStyle = {
        color: props.color,
        fontSize: '14px',
    }

    return (
        <p style={contentStyle}>{props.message}</p>
    );
}

export default ColorfulMessage;
```
:::note info
定義したコンポーネント(ColofulMessage)をタグとして使用できる
color, messageがpropsという変数としてColorfulMessageに渡される
:::

タグで囲った要素をpropsとしてコンポーネントに渡すこともできる
```react
// App.jsxに記述
const App = () => {
    return (
        <>
            <ColorfulMessage color='blue'>How are you?</ColorfulMessage>
            <ColorfulMessage color='green'>Good!</ColorfulMessage>
        </>
    );
};
```

```react
// ColofulMessage.jsxに記述
const ColorfulMessage = (props) => {
    const contentStyle = {
        color: props.color,
        fontSize: '14px',
    }

    return (
        <p style={contentStyle}>{props.children}</p>
    );
}
```
:::note info
タグで囲った要素は`props.children`として渡される
:::

javaScriptの分割代入を使えばもっと簡単に書ける
```react
// ColofulMessage.jsxに記述
const ColorfulMessage = (props) => {
    const { color, children } = props;
    const contentStyle = {
        color,
        fontSize: '14px',
    }

    return (
        <p style={contentStyle}>{children}</p>
    );
}
```
:::note info
cssではキー名と値が同じ場合、`color: color` を `color` のように省略できる
:::





# state
各コンポーネントが持つ状態のこと。
<b>Stateが変更されると再レンダリングされる。</b>
使用する場合はuseStateを使う。

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

const App = () => {
    const [num, setNum] = useState(100);
    return (
        <p>{num}</p>
    );
};
```
:::note info
`useState`を配列として分割代入した時、1番目はstateとして使用する変数名(num)、2番目はstateを変更するための関数(setNum)を取り出す
`useState(100)`は初期値を表す（初期値は100なので、numには100が表示される）
:::

stateを変更するための関数を使用することで変数の値を変更できる
```react
const App = () => {
    const [num, setNum] = useState(100);
    const onClickCountUp = () => {
        setNum(num + 1);
    };

    return (
        <>
            <button onClick={onClickCountUp}>カウントアップ！</button>
            <br/>
            <p>{num}</p>
        </>
    );
};
```
:::note info
カウントアップボタンを押すと`onClickCountUp`が呼ばれ、`setNum(num + 1)`により`num = num + 1`が実行され、numの値がボタンを押すたびに1ずつ増えていく
`setNum(1000)`にすると`num = 1000`が実行されるので、numが1000になる
:::




# useEffect
useEffectはstateの対象を限定する関数こと。関心を分離させる。

## レンダリングで気をつけること

再レンダリングがされる主なタイミングは下記の3つ。
1. stateが変更された時
1. propsの値が変更された時
1. 親のコンポーネントのstateが変更された時

:::note warn
再レンダリングが意図せずされてしまうと、思わぬバグを引き起こしてしまうので注意
:::

バグを引き起こしてしまうコードの例
```react
const App = () => {
    const [num, setNum] = useState(0);
    const [faceShowFlag, setFaceShowFlag] = useState(true);

    const onClickSwitchShowFlag = () => {
        setFaceShowFlag(!faceShowFlag);
    }

    if (num % 3 === 0) {
        setFaceShowFlag(true);
    } else {
        setFaceShowFlag(false);
    }

    return (
        <>
            <button onClick={onClickCountUp}>カウントアップ！</button>
            <br/>
            <button onClick={onClickSwitchShowFlag}>on/off</button>
            <p>{num}</p>
            {faceShowFlag && <p>😄</p>}
        </>
    );
};
```
:::note info
`num`の初期値が0のためif文で`setFaceShowFlag(true)`が実行される。しかし、stateが更新されたため、再び上から読み込みがされ、また同じif文を通ることになり、無限に再レンダリングが繰り返される。
:::

## useEffectの使い方1
最初のレンダリングの時だけ読み込ませたい処理を記述する
```react
useEffect(() => {
    console.log('useEffect!');
}, []);
```
:::note info
第2引数を空の配列にした場合、useEffect内に記述された処理は1度だけ実行される
:::

## useEffectの使い方2
関心をもたせたい変数を指定して、渡した変数に変更があった場合のみ、処理を実行されるようにする
```react
const App = () => {
    const [num, setNum] = useState(0);
    const [faceShowFlag, setFaceShowFlag] = useState(false);

    const onClickCountUp = () => {
        setNum(num + 1);
    };
    const onClickSwitchShowFlag = () => {
        setFaceShowFlag(!faceShowFlag);
    }

    useEffect(() => {
        if (num > 0 && num % 3 === 0) {
            faceShowFlag || setFaceShowFlag(true);
        } else {
            faceShowFlag && setFaceShowFlag(false);
        }
    }, [num]);

    return (
        <>
            <button onClick={onClickCountUp}>カウントアップ！</button>
            <br/>
            <button onClick={onClickSwitchShowFlag}>on/off</button>
            <p>{num}</p>
            {faceShowFlag && <p>😄</p>}
        </>
    );
};
```
:::note info
上記の場合、`num`が更新された場合のみ`useEffect`内の処理が走る
:::



# 通常のexportとdefault export
default exportの書き方
```react
// ColorfulMessage.jsxに記述
import React from 'react';

const ColorfulMessage = (props) => {
    // 省略
}

export default ColorfulMessage;
```
```react
// App.jsxに記述
import React, { useEffect, useState } from 'react';
import ColorfulMessage from './components/ColorfulMessage';

const App = () => {
    // 省略
}
```

通常のexportの書き方
```react
// ColorfulMessage.jsxに記述
import React from 'react';

export const ColorfulMessage = (props) => {
    // 省略
}
```
```react
import React, { useEffect, useState } from 'react';
import { ColorfulMessage } from './components/ColorfulMessage';

const App = () => {
    // 省略
}
```
:::note info
通常のexportの場合、分割代入で書く
:::





# 終わりに
reactは素のJavaScriptよりも、簡単にいろいろなことができて便利ですね。
もし間違っている部分があればご指摘ください。
何かの参考になれば幸いです。