React JSX

初めてReactのJSXを書く時に知っておきたかった情報をまとめています。


## 準備


### Reactを書くのに便利な拡張機能

VS Codeの拡張
ES7 React/Redux/GraphQL/React-Native snippets
https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets
rafceと書いて展開すると関数コンポーネントの雛形が作れたりします。

Chromeの拡張
React Developer tools
https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi

### create-react-app
インストールして実行

```:terminal
npx create-react-app プロジェクト名
cd プロジェクト名
npm start
```

ブラウザが起動して、Reactのロゴが回転する画面が表示されたら成功です。


### App.jsの不要な記述を削除

```:src\App.js
function App() {
  return (
    <div className="App">
    
    </div>
  );
}

export default App;
```



## インポート

外部リソースのインポート方法です。

### コンポーネントのインポート

コンポーネントを2つ作成して、App.jsに読み込んで表示してみます。

コンポーネント1

```:src\components\componentOne\ComponentOne.js
import React from 'react'

const ComponentOne = () => {

  return (

    <div className="ComponentOneWrapper">
      <p className="ComponentOneText">コンポーネント1</p>
    </div>

  )
}

export default ComponentOne
``` 

コンポーネント2

```:src\components\componentTwo\ComponentTwo.js
 import React from 'react'
 
 const ComponentTwo = () => {
 
   return (
 
     <div className="ComponentTwoWrapper">
       <p className="ComponentTwoText">コンポーネント2</p>
     </div>
 
   )
 }
 
 export default ComponentTwo
``` 

App.js

```:src\App.js
//別ファイルで作成したコンポーネントを読み込む
import ComponentOne from './components/componentOne/ComponentOne'
import ComponentTwo from './components/componentTwo/ComponentTwo'

function App() {
  return (
    <div className="App">

      {/* コンポーネントを配置 */}
      <ComponentOne/>
      <ComponentTwo/>

    </div>
  );
}

export default App;
``` 



### CSSのインポート
CSS in JSとCSS Modlesの2種類の方法を使ってみます。

#### CSS in JS
コンポーネント1はCSS in JSでスタイルを当ててみます。


```:src\components\componentOne\ComponentOne.js
import React from 'react'

//CSSを書いたJSファイルをインポートします。
import Styles from './ComponentOne.css.js'

const ComponentOne = () => {

  return (

    <div style={Styles.componentOneWrapper}>
      <p style={Styles.componentOneText}>コンポーネント1</p>
    </div>

  )
}

export default ComponentOne
``` 


```:src\components\componentOne\ComponentOne.css.js
export default {
  componentOneWrapper: {
    backgroundColor:"red",
    padding:"10px"
  },
  componentOneText: {
    color:"white",
    fontWeight:"bold"
  }
}
``` 

コンパイル後のhtml
CSSがインラインで記述されています。

```:html
<div style="background-color: red; padding: 10px;">
  <p style="color: white; font-weight: bold;">コンポーネント1</p>
</div>
```

#### CSS Modules
コンポーネント2はCSS Modulesでスタイルを当ててみます。

```:src\components\componentTwo\ComponentTwo.js
import React from 'react'
import Styles from './ComponentTwo.module.css'

const ComponentTwo = () => {

  return (

    <div className={Styles.componentTwoWrapper}>
      <p className={Styles.componentTwoText}>コンポーネント2</p>
    </div>

  )
}

export default ComponentTwo
``` 

```:src\components\componentTwo\ComponentTwo.module.css
.componentTwoWrapper {
  background-color: blue;
  padding: 10px;
}
.componentTwoText {
  color: white;
  font-weight: bold;
}
``` 

コンパイル後のhtml
クラス名が他のコンポーネントとぶつからないようにランダムな文字列が追加されています。

```:thml
<div class="ComponentTwo_componentTwoWrapper__ubZP1">
  <p class="ComponentTwo_componentTwoText__2HdZ5">コンポーネント2</p>
</div>
```

##### CSS ModulesでSCSSを使う場合

##### node-sassのインストール

```:terminal
npm i -D node-sass
```
##### ファイルの拡張子の変更
今回の場合だと、ComponentTwo.module.scssになります。
Styleをインポートする記述も忘れずに変更してください。

### 画像のインポート
img要素での表示とCSSでの表示を行っていきます。

#### img要素での表示

```:src\components\componentOne\ComponentOne.js
import React from 'react'
import Styles from './ComponentOne.css.js'

//create-react-appに用意されているlogo.svgをインポート
import Logo from '../../logo.svg';

const ComponentOne = () => {

  return (

    <div style={Styles.componentOneWrapper}>
      <p style={Styles.componentOneText}>コンポーネント1</p>

      {/* img要素のsrcにインポートしたロゴを指定 */}
      <img src={Logo}  alt="ロゴ" />
    </div>

  )
}

export default ComponentOne
``` 



#### CSSでの表示

##### CSS in JSの場合

```:src\components\componentOne\ComponentOne.css.js
 //create-react-appに用意されているlogo.svgをインポート
 import Logo from '../../logo.svg';
 
 export default {
   componentOneWrapper: {
     backgroundColor:"red",
     padding:"10px",
 
     //インポートしたロゴを指定
     backgroundImage:`url(${Logo})`,
   },
   componentOneText: {
     color:"white",
     fontWeight:"bold",
   }
 }
``` 

##### CSS Modulesの場合

```:src\components\componentTwo\ComponentTwo.module.css
.componentTwoWrapper {
  background-color: blue;
  padding: 10px;
  background-image: url(../../logo.svg);
}
.componentTwoText {
  color: white;
  font-weight: bold;
}
``` 







## 要素を動的に配置する
今回は配列の内容を表示するだけですが、配列を操作することで要素を増減することができます。


新規にコンポーネント3を作成します。

```:src\components\componentThree\ComponentThree.js
import React from 'react'

const ComponentThree = () => {

  //表示するものを配列で用意
  const members=[
    {name:"yamada"},
    {name:"suzuki"},
    {name:"sato"}
  ];

  return (

    <div>
      <ul>
        {
          members.map(member=>(
            <li key={member.id}>
              {member.name}
            </li>
          ))
        }

      </ul>
    </div>

  )
}

export default ComponentThree
```

App.js
コンポーネント3をインポートするように変更します。

```:src\App.js
//別ファイルで作成したコンポーネントを読み込む
import ComponentThree from './components/componentThree/ComponentThree'

function App() {
  return (
    <div className="App">

      {/* コンポーネントを配置 */}
      <ComponentThree/>

    </div>
  );
}

export default App;
``` 






## イベント
イベントをきっかけにして関数を実行したりできます。
ボタンを押すとConsoleに文字を表示してみます。

新規にコンポーネント4を作成します。

```:src\components\componentFour\ComponentFour.js
import React from 'react'

const ComponentFour = () => {

  const message=()=>{
    console.log("メッセージ");
  }

  return (

    <div>
       <button onClick={message}>メッセージボタン</button>
    </div>

  )

}

export default ComponentFour
```

```:src\App.js
//別ファイルで作成したコンポーネントを読み込む
import ComponentFour from './components/componentFour/ComponentFour'

function App() {
  return (
    <div className="App">

      <ComponentFour/>


    </div>
  );
}

export default App;
``` 


|イベントハンドラ|説明|
|---|---|
|onBlur|フォーカスが外れた時 |
|onFocus|フォーカスされた時|
|onChange|フォームの入力値が変更された時|
|onSelect|テキストが選択された時|
|onSelectStart|テキストが選択開始された時|
|onSubmit|フォームが送信された時 |
|onReset|フォームがリセットされた時|
|onAbort|画像読み込みが中断された時 |
|onError|画像読み込みでエラーが発生した時|
|onLoad|ページの読み込み時 |
|onUnload|ページの切り替え時|
|onClick|クリックされた時|
|onDblClick|ダブルクリックされた時|
|onKeyPress|キーを押して離した時|
|onKeyDown|キーを押した時|
|onKeyUp|キーを離した時|
|onMouseOver|マウスが乗った時|
|onMouseOut|マウスが外れた時|
|onMouseDown|マウスボタンを押した時|
|onMouseUp|マウスボタンを離した時|
|onMousemove|マウスが動いている時|






## 親要素から子要素へ情報の受け渡し
### props

親要素から子要素に値やDOMを渡せます。


新規に子コンポーネントを作成します。

```:src\components\childComponent\ChildComponent.js
import React from 'react'

//propsの指定を忘れない
const ChildComponent = (props) => {

  return (

    {/* props.親要素で指定したプロパティ名で受け取れる */},
    <div style={{color:props.color}}>

      {/* props.childrenで親から受け取ったDOMを表示 */}
      {props.children}

    </div>
  )
}

export default ChildComponent
``` 
 
 

```:src\App.js
//別ファイルで作成したコンポーネントを読み込む
import ChildComponent from './components/childComponent/ChildComponent'

function App() {
  return (
    <div className="App">

      {/* プロパティとDOMを子要素に渡す */}
      <ChildComponent color="red">
       <p>子要素に渡すDOM</p>
      </ChildComponent>

    </div>
  );
}

export default App;
``` 


### 子要素のイベントで親要素のstateを更新する

親コンポーネントからprops経由で子要素に関数を渡すと可能になります。

※この記事でここだけHooks(useState)を使用しているので、こちらもご参照ください。
[React Hooks(基本のHook)](https://qiita.com/takeshisakuma/items/39b5f2c0fe4d4c6ad378)

```:src\App.js
import React,{useState} from 'react'

//別ファイルで作成したコンポーネントを読み込む
import InputElement from './components/inputElement/InputElement';

const App = () => {

  //親要素が持つstate変数inputTextを定義
  const [inputText, setInputText] = useState("");

  //state関数inputTextを更新する関数handleInputTextChangeを定義
  const handleInputTextChange=(text)=> {
  setInputText(text);

}

return(

  <div className="App">

    {/* 子要素に親要素の */}
    <InputElement handleInputTextChange={e => handleInputTextChange(e)}/>

    {/* inputに表示された文字列を表示 */}
    <p>{inputText}</p>

  </div>

  )

}

export default App
``` 



```:src\components\inputElement\InputElement.js
import React from 'react'

const InputElement = (props) => {

  return (

    <div>
      <input onChange={(e) => props.handleInputTextChange(e.target.value)}/>
    </div>

   )

 }

export default InputElement
``` 











## formの入力要素のvalue
inputだけでなくselect、textareaも同様です。

```:jsx
{/* 初期値をvalue属性に書いてしまうと変更ができなくなる */}
<input type="text" value="初期値">

{/* defaultValue属性で初期値を与えると変更可能 */}
<input type="text" defaultValue="初期値"/>

{/* placeholder属性は使用可能 */}
<input type="text" name="atext" placeholder="プレースホルダー" />
```